为什么 2π 旋转动画不适用于 CALayer.transform?

Why 2π rotation animation doesn't work for CALayer.transform?

为什么 transform 直接使用 CATransform3D 不起作用

let rotationAnimation1 = CABasicAnimation(keyPath: #keyPath(CALayer.transform))
rotationAnimation1.toValue = CATransform3DMakeRotation(.pi * 2, 0, 0, 1)
rotationAnimation1.duration = 1

但是对 transform.rotation 使用 CGFloat 有效吗?

let rotationAnimation2 = CABasicAnimation(keyPath: "transform.rotation")
rotationAnimation2.toValue = CGFloat.pi * 2
rotationAnimation2.duration = 1

这是要玩的 Playground

当你安装一个完整的CATransform3D作为动画的toValue时,系统唯一要做的就是动画开始状态和结束状态的区别。一个变换和一个旋转 2π 的变换是相同的。因此,没有变化。

当您为 transform.rotation 制作动画时,您会向动画引擎提供有关您正在做什么以及您的意图的信息。它可以告诉您要绕 Z 轴顺时针旋转对象。

编辑:

当您创建 CAAnimation 时,核心动画会采用您在动画中设置的更改并确定如何应用它们。如果您只是提交一个更改后的 CATransform3D,Core Animation 必须比较开始和结束变换,并弄清楚如何生成从开始到结束状态的实际动画。例如,如果您旋转小于 1/2π,它将以最短的旋转让您到达那里。如果您的变换旋转 -3/2π(向另一个方向旋转 270 度),您的意图就会丢失,它仍然会旋转 +45°。如果您改为提交对 transform.rotation 的更改,您会为 Core Animation 提供更多信息。

需要注意的是 transform 属性 的动画 不是 通过分量矩阵插值完成的,而是通过分解两个开始来完成的并结束转换为原始组件(旋转、平移等),然后从插值组件重新创建转换。

让我们考虑恒等和 2π 旋转变换之间的 2 秒动画并问问自己 "What transform will be there after 1 second of animation has elapsed?"。这两个矩阵本质上都是 0 弧度旋转。 00之间的50%插值仍然是0,因此1秒后的最终矩阵也有0弧度旋转。

当你直接插入 transform.rotation 时,Core Animation 已经有了可用的原始组件——你实际上只是将旋转传递给它,不需要进行分解。 0 之间的 50% 插值是 π,因此 1 秒后的最终矩阵是预期的 π 弧度旋转。