同时分别以不同的持续时间为图层变换的旋转和缩放设置动画
Simultaneously animate the rotation and scale of a layer’s transform with different durations respectively
下面的问题是给缩放动画的持续时间覆盖了旋转动画。
有没有其他方法可以同时为 CALayer 的缩放和旋转设置不同持续时间的动画?
// Animate arrowhead rotation
CATransaction.begin()
CATransaction.setAnimationDuration(0.2)
CATransaction.setAnimationTimingFunction(CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut))
let arrowAngle = atan2(path.currentPoint.y - previousPoint.y,
path.currentPoint.x - previousPoint.x) + (.pi * 0.5)
let rotationZ = CATransform3DRotate(CATransform3DIdentity, arrowAngle, 0, 0, 1)
arrowhead.transform = rotationZ
CATransaction.commit()
// Animate arrowhead scale
CATransaction.begin()
CATransaction.setAnimationDuration(1.5)
CATransaction.setAnimationTimingFunction(CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut))
arrowhead.transform = CATransform3DConcat(rotationZ, arrowheadTransformScale)
CATransaction.commit()
它正在运行:
override func viewDidLoad() {
let box = CALayer()
box.frame = CGRect(x: 150, y: 300, width: 100, height: 100)
box.backgroundColor = UIColor.white.cgColor
view.layer.addSublayer(box)
let boxTransform = box.transform
let currentAngle = atan2(boxTransform.m12, boxTransform.m11)
let currentScale = getScale(for: box.affineTransform())
let targetAngle: CGFloat = .pi / 3
let targetScale: CGFloat = 2
// Set layer properties to their target values before animating them.
var affineTransform = CGAffineTransform(rotationAngle: targetAngle)
affineTransform = affineTransform.scaledBy(x: targetScale, y: targetScale)
box.setAffineTransform(affineTransform)
let rotate = CABasicAnimation(keyPath: "transform.rotation.z")
rotate.fromValue = currentAngle
rotate.toValue = targetAngle
rotate.duration = 2
rotate.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
let scaleUp = CABasicAnimation(keyPath: "transform.scale")
scaleUp.fromValue = currentScale
scaleUp.toValue = targetScale
scaleUp.duration = 4
scaleUp.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
let rotateAndScale = CAAnimationGroup()
rotateAndScale.animations = [rotate, scaleUp]
rotateAndScale.duration = 4
// Setting key to "transform" overwrites the implicit animation created when setting the target values before the animation.
box.add(rotateAndScale, forKey: "transform")
}
func getScale(for t: CGAffineTransform) -> CGFloat {
return sqrt(t.a * t.a + t.c * t.c)
}
下面的问题是给缩放动画的持续时间覆盖了旋转动画。
有没有其他方法可以同时为 CALayer 的缩放和旋转设置不同持续时间的动画?
// Animate arrowhead rotation
CATransaction.begin()
CATransaction.setAnimationDuration(0.2)
CATransaction.setAnimationTimingFunction(CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut))
let arrowAngle = atan2(path.currentPoint.y - previousPoint.y,
path.currentPoint.x - previousPoint.x) + (.pi * 0.5)
let rotationZ = CATransform3DRotate(CATransform3DIdentity, arrowAngle, 0, 0, 1)
arrowhead.transform = rotationZ
CATransaction.commit()
// Animate arrowhead scale
CATransaction.begin()
CATransaction.setAnimationDuration(1.5)
CATransaction.setAnimationTimingFunction(CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut))
arrowhead.transform = CATransform3DConcat(rotationZ, arrowheadTransformScale)
CATransaction.commit()
它正在运行:
override func viewDidLoad() {
let box = CALayer()
box.frame = CGRect(x: 150, y: 300, width: 100, height: 100)
box.backgroundColor = UIColor.white.cgColor
view.layer.addSublayer(box)
let boxTransform = box.transform
let currentAngle = atan2(boxTransform.m12, boxTransform.m11)
let currentScale = getScale(for: box.affineTransform())
let targetAngle: CGFloat = .pi / 3
let targetScale: CGFloat = 2
// Set layer properties to their target values before animating them.
var affineTransform = CGAffineTransform(rotationAngle: targetAngle)
affineTransform = affineTransform.scaledBy(x: targetScale, y: targetScale)
box.setAffineTransform(affineTransform)
let rotate = CABasicAnimation(keyPath: "transform.rotation.z")
rotate.fromValue = currentAngle
rotate.toValue = targetAngle
rotate.duration = 2
rotate.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
let scaleUp = CABasicAnimation(keyPath: "transform.scale")
scaleUp.fromValue = currentScale
scaleUp.toValue = targetScale
scaleUp.duration = 4
scaleUp.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
let rotateAndScale = CAAnimationGroup()
rotateAndScale.animations = [rotate, scaleUp]
rotateAndScale.duration = 4
// Setting key to "transform" overwrites the implicit animation created when setting the target values before the animation.
box.add(rotateAndScale, forKey: "transform")
}
func getScale(for t: CGAffineTransform) -> CGFloat {
return sqrt(t.a * t.a + t.c * t.c)
}