I can detect a touch of a CAShapeLayer like this (touchesEnded):
let touchLocation : CGPoint = (touch as! UITouch).locationInView(self.view)
for shape in shapes{
if CGPathContainsPoint(shape.path, nil, touchLocation, false){
print("Layer touch")
}
}
And I can animate the path of a CAShapeLayer like this:
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)
But while the animation is happening, touches aren't detected on the CAShapeLayer. Is it possible to detect a touch on the a CAShapeLayer while animating the path?
You can access the layer's presentationLayer
in order to do this. This will provide you with a rough approximation to the 'in flight' values of a given layer while animating. For example:
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")
}
}
Also, as a side note, it's generally considered bad practice to use removedOnCompletion = false
if you're not using the animation delegate. Instead of leaving the animation lingering, you should just update the layer's model values to represent its new state. You can do this through a CATransaction
to ensure that no implicit animations are generated. For example:
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()