2

我正在为 iOS 编写一条线动画,其中一条线在 CALayer 上绘制为 CGPath 中的一组点。线条从平面位置动画到具有不同 y 坐标但始终相同的 x 坐标有点像折线图动画的“模制”形状。

为了使点插值更容易,我在我的 CALayer 子类中添加了一个自定义 CGFloat 属性。我将此属性称为“动画师”(更好的名称可能是进度、插值器等)。我的想法是在此属性上添加一个简单的 CABasicAnimation,从 0.0f 到 1.0f,这样我就可以使用 Core Animation 的计时功能和插值支持,同时仍然能够轻松编写自定义动画。例如,如果一条线的点从 y = 100 变为 y = 130,那么当动画师在 0.0f 时,我在 100,当它的 1.0f 时,我在点 130,中间值给我我的中间点,我继续用这些新点重新画线以获得我的动画。

现在动画效果很好,我禁用了图层动作,添加了 needsDisplayForKey 等,但我的问题是核心动画不准确。animator 的最终值有时是 0.95 .96 等,而不是 1.0。这很好,因为浮点数存在准确性问题,但是当我的模型值更新(在将动画添加到图层之前设置为 1.0f)时,线条应该重新绘制,我应该得到准确的视觉效果。

这是另一个问题出现的地方。有时动画不会立即删除。大多数时候它会立即被删除,我没有任何问题,但有时它会持续几秒钟,有时甚至几分钟。为了测试我的动画没有被删除的理论,我在我的层中添加了一个简单的 BOOL 标志,当我们在表示层上时返回 YES 并且确实有时我看到我的最后一次 drawInContext 调用是在表示层上,动画器值为0.98967f 或其他东西,最后一次 drawInContext 调用动画器 1.0f 和表示层标志为 NO 发生得更晚。结果,除了明显可怕的用户体验之外,我的视觉跳跃并且不准确。

我已尽力解释我的问题,如果有人想查看代码,我很乐意提供我的测试项目。这里希望一些聪明的人看到这一点并可以帮助我。

编辑 1:已上传整个 Xcode 项目(包括我讨厌的编辑,以显示我尝试过的所有内容)here

编辑 2:有类似问题的人在完成时手动删除动画http://lucas.tiz.ma/blog/2012/04/18/core-animation-is-a-bit-garbage-collection-y/

谢谢。

4

1 回答 1

0

tl;dr 在 animationDidStop:finished: 委托回调中显式调用 setNeedsDisplay。

根据 Lucas Tizma 的帖子(参见上面的编辑 2),我尝试手动删除动画。我选择了一种比他基于块的方法更简单的方法,方法是将图层设置为在它们上设置的动画的代表。这样,动画开始和停止回调直接到达相关层。好吧,在 animationDidStop:finished: 回调中明确删除动画并不能解决问题。例如,有时(请参阅下面的日志,尤其是时间戳)动画会停止并检查它是否已被删除,这表明它已被删除,但是使用实际模型值的准确绘制发生在很久以后。

// animationDidStop:finished: call back code

NSLog(@"layer animation stopped");

// check if any animations exist
NSLog(@"animation keys: %@", [self animationKeys]);

// remove animations and check
NSLog(@"removing animations");
[self removeAllAnimations];
NSLog(@"animation keys: %@", [self animationKeys]);

// log

2012-10-11 11:47:16.774 ASPathAnimationTest[3017:c07] on presentation layer 1
2012-10-11 11:47:16.774 ASPathAnimationTest[3017:c07] 335 animation draw update, animator is 0.982606
2012-10-11 11:47:16.775 ASPathAnimationTest[3017:c07] startPoint: {100, 90} - endPoint: {100, 100} - newPoint: {100, 99.8261}
<snip>
2012-10-11 11:47:16.791 ASPathAnimationTest[3017:c07] startPoint: {1000, 50} - endPoint: {1000, 100} - newPoint: {1000, 99.1303}
2012-10-11 11:47:16.792 ASPathAnimationTest[3017:c07] layer animation stopped
2012-10-11 11:47:16.792 ASPathAnimationTest[3017:c07] animation keys: (null)
2012-10-11 11:47:16.793 ASPathAnimationTest[3017:c07] removing animations
2012-10-11 11:47:16.793 ASPathAnimationTest[3017:c07] animation keys: (null)
2012-10-11 11:47:16.794 ASPathAnimationTest[3017:c07] layer animation stopped
2012-10-11 11:47:16.794 ASPathAnimationTest[3017:c07] animation keys: (null)
2012-10-11 11:47:16.794 ASPathAnimationTest[3017:c07] removing animations
2012-10-11 11:47:16.795 ASPathAnimationTest[3017:c07] animation keys: (null)
2012-10-11 11:47:16.795 ASPathAnimationTest[3017:c07] layer animation stopped
2012-10-11 11:47:16.819 ASPathAnimationTest[3017:c07] animation keys: (null)
2012-10-11 11:47:16.820 ASPathAnimationTest[3017:c07] removing animations
2012-10-11 11:47:16.820 ASPathAnimationTest[3017:c07] animation keys: (null)
2012-10-11 11:47:16.821 ASPathAnimationTest[3017:c07] layer animation stopped
2012-10-11 11:47:16.821 ASPathAnimationTest[3017:c07] animation keys: (null)
2012-10-11 11:47:16.821 ASPathAnimationTest[3017:c07] removing animations
2012-10-11 11:47:16.822 ASPathAnimationTest[3017:c07] animation keys: (null)
2012-10-11 11:47:16.822 ASPathAnimationTest[3017:c07] layer animation stopped
2012-10-11 11:47:16.822 ASPathAnimationTest[3017:c07] animation keys: (null)
2012-10-11 11:47:16.823 ASPathAnimationTest[3017:c07] removing animations
2012-10-11 11:47:16.823 ASPathAnimationTest[3017:c07] animation keys: (null)
2012-10-11 11:48:00.000 ASPathAnimationTest[3017:c07] on presentation layer 0
2012-10-11 11:48:00.000 ASPathAnimationTest[3017:c07] 336 animation draw update, animator is 1.000000
<snip, there are 5 lines so draw and point logs go here>
2012-10-11 11:48:00.021 ASPathAnimationTest[3017:c07] 340 animation draw update, animator is 1.000000
2012-10-11 11:48:00.023 ASPathAnimationTest[3017:c07] startPoint: {100, 90} - endPoint: {100, 100} - newPoint: {100, 100}
<snip>
2012-10-11 11:48:00.026 ASPathAnimationTest[3017:c07] startPoint: {1000, 50} - endPoint: {1000, 100} - newPoint: {1000, 100}

在查看日志并注意到动画确实被删除的事实后,只是使用实际准确的模型值重新绘制有时直到几秒钟甚至几分钟后才会发生,我更改了 animationDidStop:finished: 委托回调以显式调用图层上的 setNeedsDisplay。答对了。

于 2012-10-11T07:45:24.220 回答