Sign component of `fromValue` / `toValue` ignored when animating `transform.scale.x` and `transform.scale.y` simultaneously
Originator: | cal.stephens | ||
Number: | rdar://FB9862872 | Date Originated: | 2022-1-28 |
Status: | Closed | Resolved: | Yes |
Product: | Core Animation API | Product Version: | |
Classification: | Incorrect/Unexpected Behavior | Reproducible: | yes |
When using `CABasicAnimation` to animate `transform.scale.x` and `transform.scale.y` simultaneously, the resulting animation is different from performing a single animation on `transform`. Specifically, the sign component of `fromValue` / `toValue` is ignored. With a simple CALayer: ```swift let textLayer = CATextLayer() textLayer.string = "Hello world" textLayer.foregroundColor = UIColor.white.cgColor textLayer.backgroundColor = UIColor.blue.cgColor textLayer.position = CGPoint(x: 200, y: 300) textLayer.bounds.size = CGSize(width: 200, height: 200) view.layer.addSublayer(textLayer) ``` these two equivalent CAAnimation configurations result in different animations at runtime: (1) animateSeparately ```swift let scaleX = CABasicAnimation(keyPath: "transform.scale.x") scaleX.duration = 1.0 scaleX.fromValue = -0.5 scaleX.toValue = -1 scaleX.repeatCount = .greatestFiniteMagnitude scaleX.autoreverses = true textLayer.add(scaleX, forKey: "transform.scale.x") let scaleY = CABasicAnimation(keyPath: "transform.scale.y") scaleY.duration = 1.0 scaleY.fromValue = -0.5 // results in same animation as `scaleY.fromValue = 0.5` scaleY.toValue = -1 // results in same animation as `scaleY.toValue = 1` scaleY.repeatCount = .greatestFiniteMagnitude scaleY.autoreverses = true textLayer.add(scaleY, forKey: "transform.scale.y") ``` (2) singleAnimation ```swift let transform = CABasicAnimation(keyPath: "transform") transform.duration = 1.0 transform.fromValue = CATransform3DMakeScale(-0.5, -0.5, 1) transform.toValue = CATransform3DMakeScale(-1, -1, 1) transform.repeatCount = .greatestFiniteMagnitude transform.autoreverses = true textLayer.add(transform, forKey: "transform") ``` I expect these two CAAnimation configurations to result in the same animation at runtime, where the layer is flipped across both the x axis and y axis.
Comments
Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!
Response
Thanks for submitting this report. This behaves as expected.
There is inherent ambiguity in a transform matrix. For example, Scale(-0.5, -1, -1) * Rotation(PI, 1, 0, 0) is the same transform matrix as Scale(-0.5, 1, 1).
If scale.y is then set to -0.5, you would not get a y-flip in the first decomposition, and that’s the “issue” you observed. There’s no “fix” for this because whichever way we decide to decompose a transform matrix for merging multiple animations, one can always find a counterexample due to the ambiguity.