在特定点停止CABasicAnimation

在特定点停止CABasicAnimation

问题描述:

我正在使用用 CABasicAnimation 创建的旋转动画。它会在2秒内旋转 UIView 。但是当触及 UIView 时,我需要能够阻止它。如果我删除动画,则视图与动画开始前的位置相同。

I'm using a rotation animation created with CABasicAnimation. It rotates a UIView over 2 seconds. But I need to be able to stop it when the UIView is touched. If I remove the animation the view is in the same position as before the animation started.

这是我的动画代码:

float duration = 2.0;
float rotationAngle = rotationDirection * ang * speed * duration;
//rotationAngle =  3*(2*M_PI);//(double)rotationAngle % (double)(2*M_PI) ;
CABasicAnimation* rotationAnimation;
rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
rotationAnimation.toValue = [NSNumber numberWithFloat: rotationAngle ];
rotationAnimation.duration = duration;
rotationAnimation.cumulative = YES;
rotationAnimation.removedOnCompletion = NO;
rotationAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
rotationAnimation.fillMode = kCAFillModeForwards;
rotationAnimation.delegate = self;

[self.view.layer addAnimation:rotationAnimation forKey:@"rotationAnimation"];

如何停止 UIView 's旋转到哪里,什么时候触摸?我知道如何管理触摸部分,但我无法弄清楚如何以动画的当前角度停止视图。

How can I stop the UIView's rotation right where it is, when it's touched? I know how to manage the touch part, but I can't figure out how to stop the view at the animation's current angle.

解决方案:
我通过获取表示层的角度,删除动画并设置视图的变换来解决问题。这是代码:

Solution: I solved the problem by getting the angle of the presentation layer, removing the animation and setting the view's transform. Here's the code:

[self.view.layer removeAllAnimations];      
CALayer* presentLayer = self.view.layer.presentationLayer; 
float currentAngle = [(NSNumber *)[presentLayer valueForKeyPath:@"transform.rotation.z"] floatValue];
self.view.transform = CGAffineTransformMakeRotation(currentAngle);


好问题!为此,了解核心动画架构会很有帮助。

Good question! For this, it's helpful to know the Core Animation architecture.

如果您查看核心动画编程指南描述了核心动画渲染架构,你可以看到有三棵树。

If you check out the diagram in the Core Animation Programming Guide that describes the Core Animation Rendering Architecture, you can see that there's three trees.

您拥有模型树。这就是您设置想要的价值的地方。然后是演示文稿树。就运行时而言,这就是几乎所发生的事情。然后,最后是渲染树。这就是用户看到的内容。

You have the model tree. That's where you set the values of what you want to happen. Then there's the presentation tree. That's what is pretty much happening as far as the runtime is concerned. Then, finally is the render tree. That's what the user sees.

在您的情况下,您想要查询演示文稿树的值。

In your case, you want to query the values of the presentation tree.

这很容易做到。对于已附加动画的视图,获取图层,对于图层,查询 presentationLayer 的值。例如:

It's easy to do. For the view that you have attached the animation, get the layer and for that layer, query the presentationLayer's values. For example:

CATransform3D myTransform = [(CALayer*)[self.view.layer presentationLayer] transform];

没有办法暂停动画中间流程。您所能做的就是查询值,将其删除,然后从您离开的位置再次重新创建它。

There's no way to "pause" an animation mid flow. All you can do is query the values, remove it, and then re-create it again from where you left off.

这有点痛苦!

看看我进入的其他一些帖子这更详细一点,例如

Have a look at some of my other posts where I go into this in a bit more detail, e.g.

当应用程序从后台恢复时,恢复动画停止的位置

不要还要忘记,当您向视图的图层添加动画时,实际上并没有更改基础视图的属性。那会发生什么?我们会在动画停止的地方得到奇怪的效果,你会看到它的原始位置。

Don't forget also that when you add an animation to a view's layer, you aren't actually changing the underlying view's properties. So what happens? We'll you get weird effects where the animation stops and you see the view in it's original position.

这就是你需要使用 CAAnimation的地方代表。看看我对这篇文章的回答,我将其覆盖:

That's where you need to use the CAAnimation delegates. Have a look at my answer to this post where I cover this:

CABasicAnimation旋转返回原始位置