Search code examples
ioscore-animation

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


Why directly using CATransform3D for transform doesn't work

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

but using CGFloat for transform.rotation works?

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

Here is the Playground to play with.


Solution

  • It's important to note that the animation of transform property is not done by component-wise matrix interpolation, instead it's done by decomposing both start and end transforms into the primitive components (rotation, translation, etc.) and then recreating the transform from interpolated components.

    Let's consider a 2 second animation between identity and 2π-rotation transform and ask ourselves "What transform will be there after 1 second of animation has elapsed?". Both matrices are essentially 0 radians rotations. 50% interpolation between 0 and 0 is still 0, and thus the final matrix after 1 second also has 0 radians rotation.

    When you interpolate transform.rotation directly Core Animation already has primitive components available – you literally just handed it the rotation and there is no need to do the decomposition. 50% interpolation between 0 and is π and thus the final matrix after 1 second is the expected π radians rotation.