问题描述
我正在使用 CABasicAnimation 旋转 CALayer 并且工作正常.问题是,当我尝试旋转同一图层时,它会在旋转之前返回到原来的位置.我的预期输出是,对于下一次轮换,它应该从它结束的地方开始.这是我的代码:
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
推荐答案
发生的情况是您在表示层中看到了动画.但是,这不会更新图层的实际位置.因此,一旦动画完成,您会看到图层原样,因为它没有改变.
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.
要修复它,请为您的 CABasicAnimation
设置一个委托,如下所示:
To fix it, set a delegate to your CABasicAnimation
as follows:
[动画 setDelegate:self];
然后,创建一个方法来设置动画完成时所需的目标属性.现在,这是令人困惑的部分.您应该在 animationDidStart
而不是 animationDidStop
上执行此操作.否则,表示层动画将完成,当您看到原始位置的 calayer
时会闪烁,然后它会在没有动画的情况下跳转到目标位置.用 animationDidStop
试试,你就会明白我的意思了.
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
not animationDidStop
. Otherwise, the presentation layer animation will finish, and you'll get a flicker as you see the calayer
in the original position then it jumps - without animation - to the target position. Try it with animationDidStop
and you'll see what I mean.
我希望这不会太混乱!
- (void)animationDidStart:(CAAnimation *)theAnimation
{
[calayer setWhateverPropertiesExpected];
}
我后来发现 Apple 推荐了一种更好的方法来做到这一点.
I later discovered that Apple recommend a much better way to do this.
Oleg Begemann 在他的博文 在使用显式 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:
// Save the original value
CGFloat originalY = layer.position.y;
接下来,在层的模型上设置 toValue.因此,图层模型具有您将要执行的任何动画的最终值:
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:
// Change the model value
layer.position = CGPointMake(layer.position.x, 300.0);
然后,您将动画设置为 fromValue 是您上面提到的原始值:
Then, you set the animation up with the animation fromValue being that original value that you noted above:
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position.y"];
// Now specify the fromValue for the animation because
// the current model value is already the correct toValue
animation.fromValue = @(originalY);
animation.duration = 1.0;
// Use the name of the animated property as key
// to override the implicit animation
[layer addAnimation:animation forKey:@"position"];
请注意,为清楚起见,上面编辑中的代码是从 Ole Begemann 的博客中复制/粘贴的
这篇关于CABasicAnimation 旋转返回原始位置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!