2016-05-08 6 views
2

時のタッチを検出CAShapeLayerは、私はこのようなCAShapeLayer(touchesEnded)のタッチを検出することができ、アニメーションスウィフト

let newShapePath = UIBezierPath(arcCenter: toPoint, radius: 20, startAngle: CGFloat(0), endAngle: CGFloat(M_PI * 2), clockwise: true).CGPath 

// animate the `path` 
let animation = CABasicAnimation(keyPath: "path") 
animation.toValue = newShapePath 
animation.duration = CFTimeInterval(duration) 

animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseIn) 
animation.fillMode = kCAFillModeBoth 
animation.removedOnCompletion = false 

shape.addAnimation(animation, forKey: animation.keyPath) 

しかし、アニメーションが行われている間、CAShapeLayerでタッチが検出されません。パスをアニメートしながらCAShapeLayerのタッチを検出することは可能ですか?

答えて

6

これを行うには、レイヤーpresentationLayerにアクセスします。これにより、アニメーション化中に特定のレイヤの「飛行中」の値におおよその近似値が得られます。たとえば:あなたはアニメーションデリゲートを使用していない場合は

for shape in shapes { 

    // gets the layer's presentation layer if it exists – else fallback on the model layer 
    let presentationLayer = shape.presentationLayer() as? CAShapeLayer ?? shape 

    if CGPathContainsPoint(presentationLayer.path, nil, touchLocation, false){ 
     print("Layer touch") 
    } 
} 

また、サイドノートとして、それは一般的に考えられています悪い習慣はremovedOnCompletion = falseを使用します。アニメーションを残しておくのではなく、新しい状態を表すようにレイヤのモデル値を更新するだけです。暗黙のアニメーションが生成されないようにするには、CATransactionを使用します。例:

let animation = CABasicAnimation(keyPath: "path") 
animation.fromValue = shape.path 
animation.toValue = newShapePath 
animation.duration = CFTimeInterval(duration) 

animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseIn) 

shape.addAnimation(animation, forKey: animation.keyPath) 

// update the layer's model values 
CATransaction.begin() 
CATransaction.setDisableActions(true) 
shape.path = newShapePath 
CATransaction.commit() 
関連する問題