同时分别为不同持续时间的图层变换的旋转和缩放设置动画

时间:2017-08-25 16:00:16

标签: ios core-animation

下面的问题是给予缩放动画的持续时间会覆盖旋转动画。

还有其他方法可以同时为不同持续时间的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()

1 个答案:

答案 0 :(得分:2)

这里有效:

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 model's animated properties to their target values. Then the subsequent animations don't require isRemovedOnCompletion and fillMode to be set which would leave the layer model out of sync.
    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)
}

Rotate and scale layer transform simultaneously