【问题标题】:Observing animated property changes in a CALayer观察 CALayer 中的动画属性变化
【发布时间】:2010-12-06 04:14:37
【问题描述】:

我有一个CABasicAnimation,它为CALayer 的属性设置动画,例如bounds.origin。我希望能够观察到属性随时间的变化,但还没有真正找到一种 100% 有效的方法。

  1. 我尝试在 presentationLayerbounds.origin 键路径上使用 KVO(键值观察)。系统抱怨对象在其观察者被释放之前被释放,导致我认为表示层只是暂时的。观察 presentationLayer.bounds.origin 作为键路径不起作用。

  2. 我尝试在另一个图层上创建一个属性并为其设置动画,例如通过在该层声明@property 并使其成为@dynamic。然而,这个新属性仅在访问表示层时(例如在动画结束时)才会更改,它似乎不会在动画运行时更新。

  3. 我在#2 中的属性上使用了needsDisplayForKey,它确实会在动画期间触发更新,但是对于这些问题:

    • 仅当CALayer 具有非零帧时才有效。由于该层可能是 CAShapeLayer 或子类,因此它可能具有零帧。
    • 看起来它会触发该层的setNeedsDisplay,但由于我实际上并没有绘制该层,只监视属性更改,所以我不想让它重绘。
  4. 我尝试安排NSTimer,并在计时器回调示例中安排presentationLayer。这也适用,但针对以下问题:

    • 计时器可能与动画更新略有不同步。
    • 由于有时原始动画会被另一个动画抢占,因此很难真正让计时器在动画运行时触发,并且仅在动画运行时触发。

有什么建议吗?这一切都将在 iPhoneOS 3.0/3.1 上实现。

【问题讨论】:

    标签: iphone objective-c macos core-animation calayer


    【解决方案1】:

    尝试使用 CADisplayLink,它旨在与动画循环保持同步。更多信息:https://ashfurrow.com/blog/animating-views-with-cadisplaylink/

    【讨论】:

      【解决方案2】:

      我想你已经列出了所有的可能性。事实上,我什至不知道#2 和#3,我写了the book on Core Animation。 ;-)

      KVO 不适用于这些属性。如果是这样就好了,但我相信这样做的原因与它所需要的开销有关。该值会非常频繁地更新,并且必须回调任何观察者。

      无论如何,我发现 NSTimer 是最可靠的方法,但现在我不确定你所说的。是什么让您认为计时器不同步?为什么只有在动画运行时才触发计时器很困难?难道你不能在定时器回调中检查你想要的条件,如果条件不满足就什么都不做吗?

      最好的问候。

      【讨论】:

      • NSTimers 的触发与实际图层何时更新无关,它们总是稍微落后或稍早于图层动画步骤。我需要的是在同时作为图层动画得到通知。最好的办法是使用 CADisplayLink(仅限 iPhone 3.1)或使用选项 #3 制作人造层以获得通知。最后,因为环境如此动态,我放弃了使用 Core Animation 来做这件事——我现在使用 NSTimer 或 CADisplayLink 来做自动滚动。
      • 当我自动滚动时,有时我要替换的图层中有一个现有的自动滚动动画,有时初始动画必须延迟 1/2 秒。因此,很难知道实际动画何时运行。 CAAnimation 委托回调也不会立即发生,因此任何依赖于它的代码都可能与动画层中已经发生的事情不同步。
      • 参见例如:developer.apple.com/mac/library/qa/qa2004/qa1385.html。 Apple 文档说“NSTimer 是一个通用计时器。它不是与显示设备绑定的计时器。时间间隔和计时器开始触发的瞬间与垂直刷新发生的时间无关。这意味着简单的方法在“60.0”赫兹创建一个定时器注定要失败——定时器将相对于实际刷新率漂移,你会丢帧或加倍帧。这也意味着定时器在任意点调用应用程序进入刷新...”
      • 这个答案对我来说很好:stackoverflow.com/questions/18827973/…
      【解决方案3】:

      对我来说最好的解决方案是同时使用 CABasicAnimation 和 CADisplayLink。您可以开始观察开始动画的变化并在其结束时完成。您也可以计算每个步骤,但要注意时序逻辑。当您使用线性时序时,它将起作用。或者您必须基于 CADisplayLink 在您的类上准备类似的逻辑(转换与时间变化保持一致)。

      【讨论】:

      • 请重新格式化文本。
      • 测试有什么问题?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-05-27
      • 2013-10-24
      • 2017-09-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-10
      相关资源
      最近更新 更多