使用CAMediaTimingFunction计算时间(t)的值

Fra*_*y I 14 bezier core-animation

在Cocoa/Touch中,CAMediaTimingFunction表示四个控制点,指定计时函数的三次贝塞尔曲线.对于我正在编写的应用程序,我希望能够在任意时间t(0 - > 1)提取所述贝塞尔曲线的结果.令我困惑的是,当我查找如何做到这一点时,结果应该是一个点,而不是标量:

B(t)=(1-t)^ 3*P0 + 3*(1-t)^ 2*t*P1 + 3*(1-t)*t ^ 2*P2 + t ^ 2*P3

但是,Apple的实现会产生一个标量值(你可以在这张图上看到他们绘制的x(t)vs t:http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Animation_Types_Timing/Articles/ Timing.html#// apple_ref/doc/uid/TP40006670-SW1)

那么Apple是否只是忽略结果的y坐标而只处理x?这看起来很奇怪,因为那时你不需要传递控制点而是控制标量,因为y根本不会影响结果.

Rap*_*aad 11

CoreAnimation可以满足CAMediaTimingFunction您的需求,但不会为给定的'x'提供'y'用于多功能(动画)使用,而只是将解决的值不透明地提供给引擎盖下的动画系统.

我自己需要它,所以构建了一个具有接口和功能的类,CAMediaTimingFunction但是使用了所需的-valueForX:方法 ; 用法示例:

RSTimingFunction *heavyEaseInTimingFunction = [RSTimingFunction timingFunctionWithControlPoint1:CGPointMake(0.8, 0.0) controlPoint2:CGPointMake(1.0, 1.0)];
CGFloat visualProgress = [heavyEaseInTimingFunction valueForX:progress];
Run Code Online (Sandbox Code Playgroud)

您可以创建轻松,缓和,易于放松或任何可以用立方贝塞尔曲线描述的曲线.实现数学基于WebCore(WebKit),这可能是CoreAnimation在引擎盖下使用的.

享受,拉斐尔


CIF*_*ter 6

不幸的是,核心动画并没有公开其动画计时的内部计算模型。然而,对我来说真正有效的是使用 Core Animation 来完成这项工作!

  1. 创建一个CALayer作为评估者
  2. 将其框架设置为((0.0, 0.0), (1.0, 1.0))
  3. 设置isHiddentrue
  4. 设置speed0.0
  5. 将此层添加到某个容器层
  6. 当您想要评估任何 时CAMediaTimingFunction,请创建一个参考动画:

    let basicAnimation = CABasicAnimation(keyPath: "bounds.origin.x")
    basicAnimation.duration = 1.0
    basicAnimation.timingFunction = timingFunction
    basicAnimation.fromValue = 0.0
    basicAnimation.toValue = containerLayer.bounds.width
    
    referenceLayer.add(basicAnimation, forKey: "evaluatorAnimation")
    
    Run Code Online (Sandbox Code Playgroud)
  7. 将参考层设置为您想要评估的 timeOffset任何标准化输入值(即,在0.0和之间):1.0

    referenceLayer.timeOffset = 0.3    // 30% into the animation
    
    Run Code Online (Sandbox Code Playgroud)
  8. 请求参考层的表示层,并获取其当前边界原点 x 值:

    if let presentationLayer = referenceLayer.presentation() as CALayer? {
        let evaluatedValue = presentationLayer.bounds.origin.x / containerLayer.bounds.width
    }
    
    Run Code Online (Sandbox Code Playgroud)

基本上,您正在使用核心动画来运行不可见层的动画。但该图层speed0.0,所以它根本不会推进动画。使用timeOffset,我们可以手动调整动画的当前位置,然后获取其表示层的 x 位置。这表示由动画驱动的该属性的当前感知值。

这有点不合常规,但并没有什么奇怪的。它尽可能忠实地表示了 a 的输出值,CAMediaTimingFunction因为 Core Animation 实际上正在使用它。

唯一需要注意的是,表示层非常接近屏幕上显示的值。Core Animation 不保证其准确性,但在我使用 Core Animation 的这些年里,我从未见过它不准确。不过,如果您的应用程序需要绝对的准确性,那么这种技术可能不是最好的。


jin*_*jin 5

注意:我不是 CoreAnimation 方面的专家。这只是我阅读您链接的文档后的理解。

苹果在这里混合了坐标系统,这造成了一些混乱。

x(t)在示例图中,表示沿着某些路径的标量进展,而不是物理坐标。

CAMediaTimingFunction 中使用的控制点用于描述此进展,而不是几何点。更令人困惑的是,x控制点实际上映射到t图上,而y控制点实际上映射到x(t)图上。

以该图为例kCAMediaTimingFunctionEaseInEaseOut,该图将通过控制点 (0,0)、(0.5,0)、(0.5,1)、(1,1) 粗略地描述。

  • @Fransisco您将此标记为答案,但正如您在评论中所述,真正的问题仍然是为给定的x获取y。你解决过这个问题吗?干杯。 (2认同)