CAShapeLayer detect touch during animation Swift

三世轮回 提交于 2019-12-11 03:17:59

问题


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?


回答1:


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


来源:https://stackoverflow.com/questions/37102573/cashapelayer-detect-touch-during-animation-swift

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!