Search code examples
objective-cmacosanimationcalayercaanimation

Mac OS: CAAnimation - seamlessly update the animation


I'm making custom UI element and I need to animate it. The problem is that at some point I need to update my animation, but when I update it, there is a visible lag/gap between current animation position (state) and new animation.

In other words, when I'm applying new animation, this animation starts from 0 position (state), while the actual (visible) state of the previous animation is different.

Here is example: (link)

<blockquote class="imgur-embed-pub" lang="en" data-id="a/q3NA31f"><a href="//imgur.com/q3NA31f"></a></blockquote><script async src="//s.imgur.com/min/embed.js" charset="utf-8"></script>

Code for animation:

CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];
anim.duration = time;
anim.repeatCount = INFINITY;
anim.fromValue = from;
anim.byValue = by;

[self.myLayer addAnimation:anim forKey:kActivityAnimationKey];

First applied animation have different time/from/by parameters.

ANY advices will be much appreciated, since I stuck on it on two days and tried everything that comes to head by this time.


Solution

  • I was able to finish this task and I will give a general answer to this question.

    If you want to update your current ongoing animation, but you're in the middle of it, you need to replace current animation with animation that will end current animation on the right place.

    For example, in my question there is an animation that have fromValue and byValue. It means, that if you'll start the same animation with different duration, it will change its current rotation state to fromValue.

    To fix this behaviour, we need to add animation that will finish our animation from current rotation state to fromValue. To get your current rotation, or other property you need to animate, we have presentationLayer of CALayer. We can set the values from it to our "closing" animation.

    How we can know when our closing animation is ended? The answer is CAAnimationDelegate. Just set up a delegate to the closing animation and when it's done - add another animation with different parameters. You can seamlessly update your animation now.

    Keep in mind that closing animation time must be a fraction of your original animation time to make things smooth. You can calculate it like this: (end state - current state) * original duration.