user2632521
user2632521

Reputation: 11

how to start a CAKeyframeAnimation from stop position

I'm using CAKeyframeAnimation to do a rotate animation. I'm using a button to trigger an animation on a layer.

I want to start the next rotate animation from the previous animation stop radian. I set fillmode with kCAFillModeForwards, yet the stop radian does not reset to original, but when I start next the rotate animation, the animation always starts from the original not from previous stop state.

Is there an solution for it?

Upvotes: 1

Views: 1206

Answers (2)

Mindy
Mindy

Reputation: 439

If you want the next rotation animation start from the pre stop state, the key point is, at the end of the pre animation you should update the model layer according to the current value of the presentation layer.

Upvotes: 0

Can
Can

Reputation: 8571

I don't fully understand the question, do you want it to keep the angle after the rotation, and that second rotation is another animation? Or do you want it to rotate indefinitely?

I'm gonna aim for both.

Keep the angle

You want it to spin it once, and then keep it in the current angle, then to rotate it again later?

Well, you need to understand how there's a "model layer" and the "presentation layer". Once the presentation layer goes (removedOnCompletion) it reverts back to the model layer, so what you may want to do, is modify the "model layer" as to give the final result.

CALayer *layer = <#self.myview.layer#>;

CGFloat angle = M_PI_4;

// Get the new transform
CATransform3D transform = CATransform3DRotate(layer.transform, angle, 0, 0, 1);

// Apply the animation to the "presentation layer"
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform"];

animation.fromValue = [NSValue valueWithCATransform3D:layer.transform];
animation.toValue   = [NSValue valueWithCATransform3D:transform];
animation.duration  = 1.0;

animation.removedOnCompletion = YES;
animation.fillMode = kCAFillModeForwards;

[layer addAnimation:animation forKey:@"spinme"];

// Apply the transform to the "model layer"
layer.transform = transform;

Notice that, by the end, I set the layer.transform, this makes it so, that when the animation ends, the model layer is up to date with the presentation layer.

Rotate indefinitely

The two key properties you should be paying attention are:

animation.cumulative = YES;
animation.repeatCount = HUGE_VALF;
  • Cumulative makes it, well.. accumulate, adding up the results from the previous transform. It doesn't revert to the original state.
  • Repeat count determines how many times it will spin, and HUGE_VALF is basically the nice way of saying infinity.

On the other hand, you can avoid using cumulative if the animation does goes a full cycle on its own. For example, the following animation:

CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];

animation.fromValue = @(0);
animation.toValue   = @(2*M_PI);
animation.duration  = 1.0;

animation.cumulative = NO;
animation.repeatCount = HUGE_VALF;
animation.removedOnCompletion = YES;
animation.fillMode = kCAFillModeForwards;

Doesn't require the cumulative flag, as it turns the full 360º (2*pi), but the repeat count is still relevant. The removed on completion is mostly optional, as the animation, in theory, will never end, only when someone else removes it.

What method you choose, it all depends on what exactly you're trying to accomplish.

Upvotes: 2

Related Questions