检测在 CAShapeLayer 中点击的位置

Posted

技术标签:

【中文标题】检测在 CAShapeLayer 中点击的位置【英文标题】:Detecting where a tap is made in CAShapeLayer 【发布时间】:2015-11-25 15:45:59 【问题描述】:

我正在尝试实现一个需要对触摸做出反应的自定义图表。我正在使用CAShapeLayer 在视图控制器视图中绘制图形。代码如下:

var PILL_GRAPH_ENDING_X_AXIS    : CGFloat!
    var PILL_GRAPH_BEGINNING_X_AXIS : CGFloat!
    var PILL_GRAPH_DRAW_WIDTH       : CGFloat!
    var PILL_GRAPH_Y_AXIS           : CGFloat!

    var graphLayer                  : CAShapeLayer!
    var tapGestureRecognizer        : UITapGestureRecognizer!

    //MARK: View Management
    override func viewDidLoad() 
        super.viewDidLoad()
        tapGestureRecognizer = UITapGestureRecognizer(target: self, action: "viewTapped:")
        view.addGestureRecognizer(tapGestureRecognizer)
    
    override func viewWillAppear(animated: Bool) 
        super.viewWillAppear(animated)
        print("View will appear has been called")
    

    override func viewWillLayoutSubviews() 
        super.viewWillLayoutSubviews()
        print("View will layout subviews")
        PILL_GRAPH_Y_AXIS = view.frame.size.height/2
        PILL_GRAPH_DRAW_WIDTH = 80
        PILL_GRAPH_ENDING_X_AXIS = view.frame.size.width-50
        PILL_GRAPH_BEGINNING_X_AXIS = 50
        drawPillGraph()
    

    //MARK: Graph Drawing

    func drawPillGraph() 
        let bezierPath = UIBezierPath()
        graphLayer = CAShapeLayer()
        //Prepare the line drawing
        bezierPath.moveToPoint(CGPoint(x: PILL_GRAPH_BEGINNING_X_AXIS, y: PILL_GRAPH_Y_AXIS))
        let endingPoint = CGPoint(x: PILL_GRAPH_ENDING_X_AXIS, y: PILL_GRAPH_Y_AXIS)
        bezierPath.addLineToPoint(endingPoint)
        graphLayer.opacity = 1.0
        graphLayer.backgroundColor = UIColor.lightGrayColor().CGColor
        graphLayer.strokeColor = UIColor.redColor().CGColor
        graphLayer.lineWidth = PILL_GRAPH_DRAW_WIDTH
        graphLayer.lineCap = kCALineCapRound
        graphLayer.path = bezierPath.CGPath
        view.layer.addSublayer(graphLayer)
    

    func viewTapped(gestureRecognizer: UITapGestureRecognizer)
        print("View tapped")

        let touch = gestureRecognizer.locationInView(self.view)

    

这将生成一个如下所示的图表:

我想要做的是能够检测何时点击红色图表以及点击点CGPoint,特别是在点击的图表中。我尝试了几种不同的方法来尝试使用hitTest:CGPointContainsPoint,但我一直无法成功实现我想要做的事情。如果有人有如何做到这一点的例子,将不胜感激。

【问题讨论】:

实现 hitTest 方法是正确的解决方案。如果您的代码不起作用,请编辑您的问题以显示该代码,我们可以帮助您调试它。 【参考方案1】:

这是我直接从我的项目中复制的一些代码(CGPathContainsPoint 代码除外)。在我的例子中,手势识别器是长按,但这就是我实现hitTest:

的方式
func didLongPressView(lpGesture:UILongPressGestureRecognizer) 
    let location = lpGesture.locationInView(self)
    let point = self.convertPoint(location, fromView: nil)

    let foundLayer = self.rootLayer!.hitTest(point)

    if let shapeLayer = foundLayer as? CAShapeLayer 
        // You've found a shape layer, see if the point is inside
        // its path
        if CGPathContainsPoint(shapeLayer.path, nil, point, false) 
            // The tap was inside the shape layer's path.

        

    


rootLayer 变量是我的层层次结构中最外层(***父级)。

【讨论】:

【参考方案2】:

Swift 3.0 中,事情变得更加简洁和不同。

    func buttonTapped(sender: UITapGestureRecognizer) 
    // Check location of tap in the View.
    let location = tapGesture?.location(in: self.view)
    // Convert location into a Point
    let point = self.view.convert(location!, from: nil)

    if shapeLayer!.path!.contains(point) 
        startAnimation()
    

或者使用您的 LongPress 示例马特...

    func didLongPressView(sender: UILongPressGestureRecognizer) 
    // Check location of long press in the View.
    let location = lpGesture?.location(in: self.rootLayer)
    // Convert location into a Point
    let point = self.rootLayer.convert(location!, from: nil)

    if shapeLayer!.path!.contains(point) 
        startAnimation()
    

即在此函数之外声明的 tapGesture/lpGesture 并且 ShapeLayer 已在 viewDidLoad 中实例化为 CAShapeLayer()(如下所示)......

    self.shapeLayer = CAShapeLayer()
    shapeLayer!.path = shapeBezier.cgPath
    shapeLayer!.fillColor = UIColor.whiteColor().cgColor
    self.view.layer.addSublayer(shapeLayer!)

【讨论】:

以上是关于检测在 CAShapeLayer 中点击的位置的主要内容,如果未能解决你的问题,请参考以下文章

如何检测 SwiftUI 中的点击位置?

如何检测iOS中最近的小按钮的点击?

检测 CAShapeLayer 笔画中的触摸

如何在 iOS 7 中检测水龙头的位置

检测旋转 CAShapeLayer 上的触摸

Unity UGUI获取鼠标在屏幕的准确点击位置