an0
an0

Reputation: 17530

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.

Upvotes: 2

Views: 224

Answers (2)

Duncan C
Duncan C

Reputation: 131418

When you install a complete CATransform3D as the toValue of an animation, the only thing the system has to go on is the difference between the starting state and ending state of the animation. A transform and a transform rotated by 2∏ are identical. Thus, no change.

When you animate transform.rotation instead, you give the animation engine information about what you are doing and what your intentions are. It can tell that you want to rotate your object around the Z axis, clockwise.

EDIT:

When you create a CAAnimation Core Animation takes the changes you set up in the animation and figures out how to apply them. If you simply submit a changed CATransform3D, Core Animation has to compare the starting and ending transform and figure out how to generate the actual animation from the start to the end state. For example, if you rotate by less than 1/2π, it will take the shortest rotation that gets you there. If your transform rotates by -3/2π (270 degrees in the other direction) your intent is lost and it still rotates by +45°. If you instead submit a change to transform.rotation, you give Core Animation more information.

Upvotes: 1

Bartosz Ciechanowski
Bartosz Ciechanowski

Reputation: 10333

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.

Upvotes: 5

Related Questions