CABasicAnimation旋转返回到原始位置

发布于 2024-12-08 12:19:50 字数 667 浏览 0 评论 0 原文

我正在使用 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"];

我的代码是否缺少任何内容?谢谢

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

旧时光的容颜 2024-12-15 12:19:50

发生的情况是您在表示层中看到动画。但是,这不会更新图层的实际位置。因此,一旦动画完成,您就会看到图层的原样,因为它没有改变。

确实值得阅读“核心动画渲染”架构”。否则这可能会非常令人困惑。

要修复此问题,请为您的 CABasicAnimation 设置委托,如下所示:

[animation setDelegate:self];

然后,创建一个方法来设置动画播放时所需的目标属性完成。现在,这是令人困惑的部分。您应该在 animationDidStart 而不是 animationDidStop 上执行此操作。否则,表示层动画将完成,当您在原始位置看到 calayer 时,您会看到闪烁,然后它会跳转(没有动画)到目标位置。使用 animationDidStop 尝试一下,您就会明白我的意思。

我希望这不会太令人困惑!

- (void)animationDidStart:(CAAnimation *)theAnimation
{
    [calayer setWhateverPropertiesExpected];
}

编辑:

我后来发现苹果推荐了一种更好的方法来做到这一点。

Oleg Begemann 在他的博客文章 使用显式 CAAnimations 时防止图层弹回原始值

基本上,您要做的就是在开始动画之前,记下图层的当前值,即原始值:

// Save the original value
CGFloat originalY = layer.position.y;

接下来,在图层模型上设置toValue。因此,图层模型具有您将要执行的任何动画的最终值:

// Change the model value
layer.position = CGPointMake(layer.position.x, 300.0);

然后,您可以使用动画 fromValue 作为您上面记下的原始值来设置动画:

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 的博客复制/粘贴的

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 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.

I hope that's not too confusing!

- (void)animationDidStart:(CAAnimation *)theAnimation
{
    [calayer setWhateverPropertiesExpected];
}

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:

// Save the original value
CGFloat originalY = layer.position.y;

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);

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"];

Note that code in edit above was copy/pasted from Ole Begemann's blog for clarity

冰葑 2024-12-15 12:19:50

如果您希望动画从结束位置开始,请将 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 the CALayer's current rotation.

Obtaining that value is tricky, but this SO post shows you how: https://stackoverflow.com/a/6706604/1072846

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文