簡體   English   中英

檢測貝塞爾曲線路徑內的點擊

[英]Detecting tap inside a bezier path

我有一個 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];
}

我想檢測這個貝塞爾曲線路徑內的點擊,而不是 UIView 內部和路徑外部的點。 例如在這種情況下,如果我的觸摸坐標是 (10, 10),則不應檢測到它。 我知道 CGContextPathContainsPoint 但是當觸摸在路徑內時它沒有幫助。 有沒有辦法檢測貝塞爾路徑內的觸摸事件?

有一個函數CGPathContainsPoint()它可能對您有用。

如果您從超級視圖獲得手勢點,也要小心,您的測試坐標可能不正確。 您有一種從特定視圖的坐標系轉換點或轉換為特定視圖坐標系的方法:

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

試試 UIBezierPath 的方法

func contains(_ point: CGPoint) -> Bool

返回一個布爾值,指示接收器包圍的區域是否包含指定的點。

快速檢測貝塞爾曲線內的點擊:-

在最新的 swift 中很簡單,按照這些步驟操作,您將獲得 UIBezierPath 觸摸事件。

第 1 步:- 在添加 UIBeizerPath 的視圖上初始化 Tap 事件。

///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
        }
    }



更新:斯威夫特 4

第 1 步:- 在添加 UIBeizerPath 的視圖上初始化 Tap 事件。

///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
    }
}

Swift 3.1 中的解決方案(從此處移植 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
        }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM