i'm rotating a CALayer using CABasicAnimation and works fine. The problem is, when I try to rotate the same layer, it returns back to its original position before it will rotate. My expected output is that, for the next rotation, it should start from where it has ended. Here's my code:
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];
animation.fromValue = 0;
animation.toValue = [NSNumber numberWithFloat:3.0];
animation.duration = 3.0;
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeForwards;
animation.autoreverses = NO;
[calayer addAnimation:animation forKey:@"rotate"];
Is there anything missing on my code? thanks
If you want the animation to start from where it has ended, then set the
fromValue
property to theCALayer
's current rotation.Obtaining that value is tricky, but this SO post shows you how: https://stackoverflow.com/a/6706604/1072846
What's happening is that you're seeing the animation in the presentation layer. However, that doesn't update the actual position of your layer. So, once the animation finishes, you see the layer as it was because it hasn't changed.
It's really worth reading the "Core Animation Rendering Architecture". Otherwise this can be very confusing.
To fix it, set a delegate to your
CABasicAnimation
as follows:[animation setDelegate:self];
Then, create a method to set your target properties that you want when the animation completes. Now, here's the confusing part. You should do this on
animationDidStart
notanimationDidStop
. Otherwise, the presentation layer animation will finish, and you'll get a flicker as you see thecalayer
in the original position then it jumps - without animation - to the target position. Try it withanimationDidStop
and you'll see what I mean.I hope that's not too confusing!
EDIT:
I later discovered that Apple recommend a much better way to do this.
Oleg Begemann has a nice description of the correct technique in his blog post Prevent Layers from Snapping Back to Original Values When Using Explicit CAAnimations
Basically what you do is before you start the animation, you take a note of the layer's current value, i.e., the original value:
Next, set the toValue on the layer's model. Therefore the layer model has the final value of whatever animation you are about to do:
Then, you set the animation up with the animation fromValue being that original value that you noted above:
Note that code in edit above was copy/pasted from Ole Begemann's blog for clarity