how the button can be rotated by 360 degree for duration of time 30 sec and after that the button stop rotation.
A 360 rotation animation is only a few lines of code with Core Animation.
CABasicAnimation *rotate =
[CABasicAnimation animationWithKeyPath:#"transform.rotation"];
rotate.byValue = #(M_PI*2); // Change to - angle for counter clockwise rotation
rotate.duration = 30.0;
[yourButton.layer addAnimation:rotate
forKey:#"myRotationAnimation"];
By using the byValue property you are doing a relative rotation of 360 degrees to whatever rotation was there before (compared to explicitly specifying the from and to values). This means that the above code will rotate the button 360 degrees even if it is already rotated. All the answers that explicitly specify an end transform are assuming that the button isn't already rotated.
The above example is as small as possible to do just what you asked for ("be rotated by 360 degree for duration of time 30 sec"). If you want to have more control you can optionally make the animation start and/or stop slowly by specifying a timing function
rotate.timingFunction =
[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
If you haven't already added QuarzCore.framework to your project you will need to do so. Also #import <QuartzCore/QuartzCore.h> in the top of your source file.
CATransform3D myRotationTransform = CATransform3DRotate(Yourbutton.layer.transform, -1, 0.0, 0.0, 1.0);
Yourbutton.layer.transform = myRotationTransform;
CABasicAnimation* animation = [CABasicAnimation animationWithKeyPath:#"transform.rotation.z"];
animation.fromValue = [NSNumber numberWithFloat:0.0f];
animation.toValue = [NSNumber numberWithFloat: -1];
animation.duration = 30;
animation.repeatCount = 1;
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
[Yourbutton.layer addAnimation:animation forKey:#"MyAnimation"];
Should work as needed! don't forget to include quartz.framework!
Well I just used
Being self.buttonImageView the ImageView you need to rotate.
[UIView animateKeyframesWithDuration:0.5 delay:0 options:UIViewKeyframeAnimationOptionCalculationModeLinear animations:^{
[UIView addKeyframeWithRelativeStartTime:0.0 relativeDuration:0.25 animations:^{
self.buttonImageView.transform= CGAffineTransformMakeRotation(M_PI);
}];
[UIView addKeyframeWithRelativeStartTime:0.5 relativeDuration:0.25 animations:^{
self.buttonImageView.transform= CGAffineTransformMakeRotation(-2* M_PI);
}];
} completion:^(BOOL finished) {
[self.map setCenterCoordinate:self.map.userLocation.location.coordinate animated:YES];
self.buttonImageView.transform= CGAffineTransformMakeRotation(2* M_PI);
}];
[UIView animateWithDuration:.30f animations:^{
btnGallery.transform = CGAffineTransformRotate(CGAffineTransformIdentity, -M_PI);
}];
Related
In this code i am using animation.But at a time i need to change the image alpha value also.
-(void)animation
{
CGPoint point = CGPointMake(imgView.frame.origin.x, imgView.frame.origin.y);
imgView.layer.position = point;
CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:#"position.x"];
anim.fromValue = [NSValue valueWithCGPoint:point];
anim.toValue = [NSValue valueWithCGPoint:CGPointMake(point.x + 50, point.y)];
anim.duration = 10.0f;
anim.repeatCount =1;
anim.removedOnCompletion = YES;
anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
[imgView.layer addAnimation:anim forKey:#"position.x"];
imgView.layer.position = point;
}
You can use the opacity key of CABasicAnimation for doing this:
CABasicAnimation *alphaAnimation = [CABasicAnimation animationWithKeyPath:#"opacity"];
alphaAnimation.fromValue = [NSNumber numberWithFloat:1.0];
alphaAnimation.toValue = [NSNumber numberWithFloat:0.0];
[imgView.layer addAnimation:alphaAnimation forKey:#"opacity"];
Edit:
For animating through specified values you can use CAKeyframeAnimation:
CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:#"opacity"];
animation.duration = 10.0f;
animation.repeatCount = 1;
animation.values = [NSArray arrayWithObjects:
[NSNumber numberWithFloat:1.0,
[NSNumber numberWithFloat:0.5],
[NSNumber numberWithFloat:1.0],nil];
animation.keyTimes = [NSArray arrayWithObjects:
[NSNumber numberWithFloat:0.0],
[NSNumber numberWithFloat:5.0],
[NSNumber numberWithFloat:10.0], nil];
[imgView.layer addAnimation:animation forKey:#"opacity"];
In order to decrease the alpha as the same time/rate the x position of your view is moving, just put the position setting code together with the alpha setting code in the same block of animation, like below:
CGPoint finalPoint = CGPointMake(500, imgView.center.y); //change for any final point you want
CGFloat finalAlpha = 0.0; //change the final alpha as you want
UIView animateWithDuration:1.0 animations:^{ //change the duration as you want
imgView.alpha = finalAlpha;
imgView.center = finalPoint;
}];
This "fades to invisible" self.view in 500ms.
Anything you do prior to invoking it will be set "immediately", everything you set within the `animation' block (like setting new frame coordinates) will be interpolated over the specified duration.
[UIView animateWithDuration:0.50
delay:0.0
options:( UIViewAnimationOptionAllowUserInteraction
| UIViewAnimationOptionBeginFromCurrentState
| UIViewAnimationOptionCurveEaseInOut)
animations:^ {
self.view.alpha = 0.0f ;
}
completion: ^(BOOL){
[self.view removeFromSuperview] ;
self.view = nil ;
}
] ;
You may use a CABasicAnimation object (a different one because you will animate a different KeyPath, namely alpha, for this) and use NSNumbers for fromValue and toValue.
Another (and easiest) way is to use the UIView helper methods dedicated to animation ( animateWithDuration:… and all), especially if you have to animate multiple properties at the same time (you may animate both the frame and the alpha with the same animation block if it fits your needs and simplify your code).
You can also mix CABasicAnimation for the frame and [UIView animateWithDuration:…] for the alpha, whatever combination you need depending on if your animations are complex and need to be customized (custom timing function, non-linear animation, …) or not.
//your code of changing x position will be here
now implement my code which is written below.
UIView animateWithDuration:1.0 animations:^{
imgView.alpha = 0.5;//must be in between 0 to 1
}];
now when your imageview move to next position as you are saying, write below code
//your code for imageview for next position..
now implement below code...
UIView animateWithDuration:0.5 animations:^{
imgView.alpha = 1.0;//must be in between 0 to 1
}];
let me know it is working or not!!!! Hope it helps...
Happy Coding!!!
I'm animating a clock arm from pointing towards 12 o'clock to the current time. If it is say, 11 o'clock, I want the arm to rotate clockwise to the 11 o'clock position. But of course if I use:
CGAffineTransform rotation = CGAffineTransformMakeRotation(2*M_PI*11/12);
[UIView animateWithDuration:3.0
animations:^{
clockArm.transform = rotation;
}];
the rotation goes counterclockwise. I tried:
CGFloat angle = 2*M_PI*11/12;
CGAffineTransform firstRotation = CGAffineTransformMakeRotation(M_PI-0.001);
CGFloat firstRotationTime = 3.0*(M_PI/angle);
CGAffineTransform secondRotation = CGAffineTransformMakeRotation(angle);
CGFloat secondRotationTime = 3.0 - firstRotationTime;
[UIView animateWithDuration:firstRotationTime
delay:0.0
options:UIViewAnimationCurveLinear
animations:^{
self.clockArm1.transform = firstRotation;
}
completion:^(BOOL finished) {
[UIView animateWithDuration:secondRotationTime
delay:0.0
options:UIViewAnimationCurveLinear
animations:^{
self.clockArm1.transform = secondRotation;
}
completion:^(BOOL finished){
}];
}];
The animation does go clockwise, but it is choppy - the animation still seems to be doing a UIViewAnimationEaseInOut for the first animation. What am I doing wrong, or is there another way to accomplish what I want?
You can use the completion block of CATransaction to set the rotation property of the view when the animation has finished. The following function worked in my test case:
- (void) rotateViewAnimated:(UIView*)view
withDuration:(CFTimeInterval)duration
byAngle:(CGFloat)angle
{
[CATransaction begin];
CABasicAnimation *rotationAnimation;
rotationAnimation = [CABasicAnimation animationWithKeyPath:#"transform.rotation.z"];
rotationAnimation.byValue = [NSNumber numberWithFloat:angle];
rotationAnimation.duration = duration;
rotationAnimation.removedOnCompletion = YES;
[CATransaction setCompletionBlock:^{
view.transform = CGAffineTransformRotate(view.transform, angle);
}];
[view.layer addAnimation:rotationAnimation forKey:#"rotationAnimation"];
[CATransaction commit];
}
You use it like
[self rotateViewAnimated:self.clockArm1 withDuration:3.0 byAngle:2*M_PI*11./12.];
Thanks for #Martin R 's accepted answer. I edited a bit:
I replaced this line
rotationAnimation.removedOnCompletion = YES;
with these two lines:
rotationAnimation.removedOnCompletion = NO;
rotationAnimation.fillMode = kCAFillModeForwards;
Then, in the CompletionBlock, I added one more line:
[view.layer removeAllAnimations];
So, the code finally becomes:
- (void) rotateViewAnimated:(UIView*)view
withDuration:(CFTimeInterval)duration
byAngle:(CGFloat)angle
{
[CATransaction begin];
CABasicAnimation *rotationAnimation;
rotationAnimation = [CABasicAnimation animationWithKeyPath:#"transform.rotation.z"];
rotationAnimation.byValue = [NSNumber numberWithFloat:angle];
rotationAnimation.duration = duration;
// changed by me
rotationAnimation.removedOnCompletion = NO;
rotationAnimation.fillMode = kCAFillModeForwards;
[CATransaction setCompletionBlock:^{
view.transform = CGAffineTransformRotate(view.transform, angle);
// added by me
[view.layer removeAllAnimations]; // this is important
}];
[view.layer addAnimation:rotationAnimation forKey:#"rotationAnimation"];
[CATransaction commit];
}
My references are from:
1, https://stackoverflow.com/a/3586433/2481444
2, After rotating a CALayer using CABasicAnimation the layer jumps back to it's unrotated position
As mentioned in comments, try this iphone UIImageView rotation
or UIView Infinite 360 degree rotation animation?
#import <QuartzCore/QuartzCore.h>
- (void) runSpinAnimationWithDuration:(CGFloat) duration;
{
CABasicAnimation* rotationAnimation;
rotationAnimation = [CABasicAnimation animationWithKeyPath:#"transform.rotation.z"];
rotationAnimation.toValue = [NSNumber numberWithFloat: M_PI * 2.0 /* full rotation*/ * rotations * duration ];
rotationAnimation.duration = duration;
rotationAnimation.cumulative = YES;
rotationAnimation.repeatCount = 1.0;
rotationAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
[myView.layer addAnimation:rotationAnimation forKey:#"rotationAnimation"];
}
I am rotating the Image 360 clockwise using the CABasicAnimation, and the code which I am using is
CALayer* _caLayer = [CALayer layer];
_caLayer.contents = (id)_logo.CGImage;
_caLayer.frame = CGRectMake(65,158, 180,55);
[self.view.layer addSublayer:_caLayer];
CABasicAnimation* rotation;
rotation = [CABasicAnimation animationWithKeyPath:#"transform.rotation"];
rotation.fromValue = [NSNumber numberWithFloat:0];
rotation.toValue = [NSNumber numberWithFloat:((360*M_PI)/180)];
rotation.duration = 1.4f;
//rotation.beginTime = CACurrentMediaTime() +1;
rotation.repeatCount = 2.0;
rotation.fillMode = kCAFillModeForwards;
[_caLayer addAnimation:rotation forKey:#"360"];
The animation is working fine.. But I cant figure out one thing. I want to start animate the image from smaller size and ends with the normal size. You have seen in movies like some newspapers will rotate fast and they fade in and finally we will see the paper in the screen fully. I am trying to do that way. I dont know how to do it, please !
You can use the following also, will works like a charm
[UIView beginAnimations:#"fade in" context:nil];
[UIView setAnimationDuration:1.0];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
_imageView.alpha = 0.0;
_newImageView.alpha = 1.0;
[UIView commitAnimations];
Set the imageView frame before animation: [imageView setFrame: CGRectMake(your Frame)];
then keep on increasing the frame in the animation using a loop or something..
I'm rotating an arrow by 45 degrees. When an animation ends, the arrow returns to its original state (0 degrees). I need that the arrow doesn't return to original state and it will be rotate by 45 degrees at the end of animation.
CABasicAnimation *fullRotationShort = [CABasicAnimation animationWithKeyPath:#"transform.rotation"];
fullRotationShort.fromValue = [NSNumber numberWithFloat:0];
fullRotationShort.toValue = [NSNumber numberWithFloat:M_PI/28*4.7];
fullRotationShort.duration = 1.0f;
fullRotationShort.repeatCount = 1;
[imgViewArrowShort.layer addAnimation:fullRotationShort forKey:nil];
Assuming your arrow is a UIImageView named arrow.
You really don't need such complicated CAAnimations for this.
[UIView animateWithDuration:1.0 animations:^{
arrow.transform = CGAffineTransformMakeRotation(0.25 * M_PI);
}];
Set the property:
fullRotationShort.fillMode = kCAFillModeForwards;
fullRotationShort.cumulative = YES;
fullRotationShort.removedOnCompletion=NO;
Is there a way to let a view rotate forever, with an specified speed? I need that for an indicator kind of thing. I know there is this weird Lxxxxx00ff constant (don't remember it exactly) that stands for "forever".
You can use HUGE_VAL for floating value (if I remember correctly, repeatCount property for animation is a float).
To setup animation you can create CAAnimation object using +animationWithKeyPath: method:
CABasicAnimation* animation = [CABasicAnimation animationWithKeyPath:#"transform.rotation.z"];
animation.fromValue = [NSNumber numberWithFloat:0.0f];
animation.toValue = [NSNumber numberWithFloat: 2*M_PI];
animation.duration = 3.0f;
animation.repeatCount = HUGE_VAL;
[rotView.layer addAnimation:animation forKey:#"MyAnimation"];
If I remember correctly creating this kind of rotation using just UIView animations is impossible because rotations on 360 degrees (2*M_PI radians) are optimized to no rotation at all.
Edit: Added a Swift version.
let animation = CABasicAnimation(keyPath: "transform.rotation.z")
animation.fromValue = NSNumber(value: 0.0)
animation.toValue = NSNumber(value: 2*Double.pi)
animation.duration = 3.0
animation.repeatCount = Float.greatestFiniteMagnitude
rotView.layer.add(animation, forKey: "MyAnimation")
my solution for this is a bit hacky since it doesn't use core animation but at least it works truly forever and doesn't require you to setup multiple animation steps.
...
// runs at 25 fps
NSTimer* timer = [NSTimer scheduledTimerWithTimeInterval:1.0/25
target:self
selector:#selector(rotate)
userInfo:nil
repeats:YES];
[timer fire];
...
- (void)rotate {
static int rotation = 0;
// assuming one whole rotation per second
rotation += 360.0 / 25.0;
if (rotation > 360.0) {
rotation -= 360.0;
}
animatedView.transform = CGAffineTransformMakeRotation(rotation * M_PI / 180.0);
}
my bet is:
-(void)animationDidStopSelector:... {
[UIView beginAnimations:nil context:NULL];
// you can change next 2 settings to setAnimationRepeatCount and set it to CGFLOAT_MAX
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(animationDidStopSelector:...)];
[UIView setAnimationDuration:...
[view setTransform: CGAffineTransformRotate(CGAffineTransformIdentity, 6.28318531)];
[UIView commitAnimations];
}
//start rotation
[self animationDidStopSelector:...];
ok better bet:
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationRepeatCount: CGFLOAT_MAX];
[UIView setAnimationDuration:2.0f];
[view setTransform: CGAffineTransformMakeRotation(6.28318531)];
[UIView commitAnimations];