检测CAShapeLayer中的点击位置

时间:2015-11-25 15:45:59

标签: ios swift uiview uikit cashapelayer

我正在尝试实现需要对触摸作出反应的自定义图表。我使用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)

    }

这将产生如下图:

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

2 个答案:

答案 0 :(得分: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变量是我的图层层次结构中的最外层(顶级父级)。

答案 1 :(得分:0)

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 示例Matt ...

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