CABasicAnimation旋转返回到原始位置
我正在使用 CABasicAnimation 旋转 CALayer 并且工作正常。问题是,当我尝试旋转同一层时,它会在旋转之前返回到其原始位置。我的预期输出是,对于下一次轮换,它应该从结束的地方开始。这是我的代码:
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"];
我的代码是否缺少任何内容?谢谢
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
发生的情况是您在表示层中看到动画。但是,这不会更新图层的实际位置。因此,一旦动画完成,您就会看到图层的原样,因为它没有改变。
确实值得阅读“核心动画渲染”架构”。否则这可能会非常令人困惑。
要修复此问题,请为您的
CABasicAnimation
设置委托,如下所示:[animation setDelegate:self];
然后,创建一个方法来设置动画播放时所需的目标属性完成。现在,这是令人困惑的部分。您应该在
animationDidStart
而不是animationDidStop
上执行此操作。否则,表示层动画将完成,当您在原始位置看到calayer
时,您会看到闪烁,然后它会跳转(没有动画)到目标位置。使用animationDidStop
尝试一下,您就会明白我的意思。我希望这不会太令人困惑!
编辑:
我后来发现苹果推荐了一种更好的方法来做到这一点。
Oleg Begemann 在他的博客文章 使用显式 CAAnimations 时防止图层弹回原始值
基本上,您要做的就是在开始动画之前,记下图层的当前值,即原始值:
接下来,在图层模型上设置toValue。因此,图层模型具有您将要执行的任何动画的最终值:
然后,您可以使用动画 fromValue 作为您上面记下的原始值来设置动画:
请注意,为了清楚起见,上面编辑中的代码是从 Ole Begemann 的博客复制/粘贴的
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
如果您希望动画从结束位置开始,请将
fromValue
属性设置为CALayer
的当前旋转。获取该值很棘手,但是这篇文章向您展示了如何操作:https://stackoverflow.com/a/6706604/1072846
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