2017-08-25 17 views
0

以下の問題は、スケールアニメーションに与えられた時間が回転アニメーションを上書きすることです。レイヤーのトランスフォームの回転とスケールをそれぞれ異なる時間で同時にアニメーション化

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() 
+0

@mattを異なる期間でレイヤーのスケールと回転をアニメーション達成する方法はありますか? – dxb

+0

@mattこのテクニックで変換の特定の側面をターゲットにしました。arrowhead.setValue(arrowAngle、forKeyPath: "transform.rotation.z") ' – dxb

+0

@mattアニメーション全体に' kCAMediaTimingFunctionLinear' ? – dxb

答えて

1

ここでは、働いている:

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

関連する問題