检测bezier路径内的水龙头

时间:2014-03-27 15:16:16

标签: ios objective-c core-graphics uibezierpath

我有一个UIView,它作为子视图添加到我的视图控制器。我在这个观点上画了一条更好的路径。我的drawRect实现在

之下
- (void)drawRect:(CGRect)rect
{
    CGContextRef context = UIGraphicsGetCurrentContext();
    UIBezierPath *bpath = [UIBezierPath bezierPath];

    [bpath moveToPoint:CGPointMake(50, 50)];
    [bpath addLineToPoint:CGPointMake(100, 50)];
    [bpath addLineToPoint:CGPointMake(100, 100)];
    [bpath addLineToPoint:CGPointMake(50, 100)];
    [bpath closePath];

    CGContextAddPath(context, bpath.CGPath);
    CGContextSetStrokeColorWithColor(context,[UIColor blackColor].CGColor);
    CGContextSetLineWidth(context, 2.5);
    CGContextStrokePath(context);
    UIColor *fillColor = [UIColor colorWithRed:0.0 green:0.0 blue:0.5 alpha:0.7];
    [fillColor setFill];
    [bpath fill];
}

我希望在此bezier路径中检测tap,但不是在UIView内部和路径外部的点。例如,在这种情况下,如果我的触摸坐标是(10,10),则不应检测到它。我知道CGContextPathContainsPoint但是当触摸在路径内时它没有帮助。有没有办法检测bezier路径内的触摸事件?

4 个答案:

答案 0 :(得分:17)

有一个函数CGPathContainsPoint()它可能对你的情况有用。

如果从superview获得手势点,也要小心,测试时坐标可能不正确。您有一种方法可以将Point转换为特定视图的坐标系:

- (CGPoint)convertPoint:(CGPoint)point toView:(UIView *)view
- (CGPoint)convertPoint:(CGPoint)point fromView:(UIView *)view

答案 1 :(得分:8)

尝试UIBezierPath' method

func contains(_ point: CGPoint) -> Bool
  

返回一个布尔值,指示是否包含的区域   接收器包含指定的点。

答案 2 :(得分:6)

在swift中检测bezier路径内的tap: -

最新的swift非常简单,请按照以下步骤进行UIBezierPath触摸事件。

步骤1: - 在添加了UIBeizerPath的视图上初始化点击事件。

///Catch layer by tap detection let tapRecognizer:UITapGestureRecognizer = UITapGestureRecognizer.init(target: self, action: #selector(YourClass.tapDetected(_:))) viewSlices.addGestureRecognizer(tapRecognizer)

第2步: - 制作" tapDetected"方法

  //MARK:- Hit TAP
public func tapDetected(tapRecognizer:UITapGestureRecognizer){
    let tapLocation:CGPoint = tapRecognizer.locationInView(viewSlices)
    self.hitTest(CGPointMake(tapLocation.x, tapLocation.y))


}

第3步: - 制作" hitTest"最终方法

  public func hitTest(tapLocation:CGPoint){
        let path:UIBezierPath = yourPath
        if path.containsPoint(tapLocation){
            //tap detected do what ever you want ..;)
        }else{
             //ooops you taped on other position in view
        }
    }



更新:Swift 4

步骤1: - 在添加了UIBeizerPath的视图上初始化点击事件。

///Catch layer by tap detection
let tapRecognizer = UITapGestureRecognizer(target: self, action: #selector(YourClass.tapDetected(tapRecognizer:)))
viewSlices.addGestureRecognizer(tapRecognizer)

第2步: - 制作" tapDetected"方法

public func tapDetected(tapRecognizer:UITapGestureRecognizer){
    let tapLocation:CGPoint = tapRecognizer.location(in: viewSlices)
    self.hitTest(tapLocation: CGPoint(x: tapLocation.x, y: tapLocation.y))
}

第3步: - 制作" hitTest"最终方法

private func hitTest(tapLocation:CGPoint){
    let path:UIBezierPath = yourPath

    if path.contains(tapLocation){
        //tap detected do what ever you want ..;)
    }else{
        //ooops you taped on other position in view
    }
}

答案 3 :(得分:1)

Swift 3.1中的解决方案(移植来自here的Apple推荐解决方案)

func containsPoint(_ point: CGPoint, path: UIBezierPath, inFillArea: Bool) -> Bool {

        UIGraphicsBeginImageContext(self.size)

        let context: CGContext? = UIGraphicsGetCurrentContext()
        let pathToTest = path.cgPath
        var isHit = false

        var mode: CGPathDrawingMode = CGPathDrawingMode.stroke

        if inFillArea {

            // check if UIBezierPath uses EO fill
            if path.usesEvenOddFillRule {
                mode = CGPathDrawingMode.eoFill
            } else {
                mode = CGPathDrawingMode.fill
            }
        } // else mode == stroke

        context?.saveGState()
        context?.addPath(pathToTest)

        isHit = (context?.pathContains(point, mode: mode))!
        context?.restoreGState()

        return isHit
        }