检测 UIBezierPath 笔划上的触摸,而不是填充

发布于 2024-11-10 03:52:58 字数 2927 浏览 0 评论 0 原文

可能的重复:
如何检查用户是否在附近点击CGPath?

我从这里遵循Apple的指南

http://developer.apple.com/library/ios/#documentation/2DDrawing/Conceptual/DrawingPrintingiOS/BezierPaths/BezierPaths.html

尝试仅检测触摸部分的触摸事件我的 UIBezierPath。如果我使用 UIBezierPath 方法 containsPoint,它工作正常,但它会检测 UIBezierPath 的笔划和填充部分上的触摸事件,并且我希望它仅发生在笔划部分上。

按照Apple的指南(在链接的清单3-6中),我创建了这个函数:

- (BOOL)containsPoint:(CGPoint)point onPath:(UIBezierPath*)path inFillArea:(BOOL)inFill
{
    CGContextRef context = UIGraphicsGetCurrentContext();    
    CGPathRef cgPath = path.CGPath;    
    BOOL    isHit = NO;

    // Determine the drawing mode to use. Default to    
    // detecting hits on the stroked portion of the path.    
    CGPathDrawingMode mode = kCGPathStroke;    
    if (inFill)        
    {   
        // Look for hits in the fill area of the path instead.
        if (path.usesEvenOddFillRule)
            mode = kCGPathEOFill;
        else
            mode = kCGPathFill;
    }

    // Save the graphics state so that the path can be
    // removed later.
    CGContextSaveGState(context);
    CGContextAddPath(context, cgPath);

   // Do the hit detection.
   isHit = CGContextPathContainsPoint(context, point, mode);
   CGContextRestoreGState(context);
   return isHit;
}

当我调用它时,我得到:

错误:CGContextSaveGState:无效的上下文0x0
错误:CGContextAddPath:无效上下文 0x0
错误:CGContextPathContainsPoint:无效上下文 0x0
错误:CGContextRestoreGState:无效的上下文 0x0

这是我的视图的drawRect函数,以及创建路径的代码:

- (UIBezierPath *) createPath {
    static UIBezierPath *path = nil;
    if(!path) {
        path = [[UIBezierPath bezierPathWithOvalInRect:CGRectMake(35, 45, 250, 250)] retain];
        path.lineWidth = 50.0;
        [path closePath];
    }    
    return path;
}

/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
*/ 
- (void)drawRect:(CGRect)rect
{
    // Drawing code

    //draw a circle
    UIBezierPath *aPath = [self createPath];

    //set stroke width
    aPath.lineWidth = 50.0;

    //set stroke color
    [[UIColor blueColor] setStroke];

    //stroke path
    [aPath stroke];

    //close path
    [aPath closePath];

    //add a label at the "top"
    UILabel *topLabel;
    topLabel = [[UILabel alloc]initWithFrame:CGRectMake(120, -5, 80, 25)];
    topLabel.text = @"The Top";
    [self addSubview:topLabel];
}

然后我尝试调用touchesMoved内部的containsPoint函数,如下所示:

if (![self containsPoint:c onPath:[self createPath] inFillArea:NO]) return;

Possible Duplicate:
How can I check if a user tapped near a CGPath?

I'm following Apple's guide from here

http://developer.apple.com/library/ios/#documentation/2DDrawing/Conceptual/DrawingPrintingiOS/BezierPaths/BezierPaths.html

to try and detect a touch event only on the stroked portion of my UIBezierPath. If I use the UIBezierPath method, containsPoint, it works fine, but it detects touch events on the stroke and the fill portion of the UIBezierPath, and I want it to only occur on the stroked portion.

Following Apple's guide (at listing 3-6 of the link), I created this function:

- (BOOL)containsPoint:(CGPoint)point onPath:(UIBezierPath*)path inFillArea:(BOOL)inFill
{
    CGContextRef context = UIGraphicsGetCurrentContext();    
    CGPathRef cgPath = path.CGPath;    
    BOOL    isHit = NO;

    // Determine the drawing mode to use. Default to    
    // detecting hits on the stroked portion of the path.    
    CGPathDrawingMode mode = kCGPathStroke;    
    if (inFill)        
    {   
        // Look for hits in the fill area of the path instead.
        if (path.usesEvenOddFillRule)
            mode = kCGPathEOFill;
        else
            mode = kCGPathFill;
    }

    // Save the graphics state so that the path can be
    // removed later.
    CGContextSaveGState(context);
    CGContextAddPath(context, cgPath);

   // Do the hit detection.
   isHit = CGContextPathContainsPoint(context, point, mode);
   CGContextRestoreGState(context);
   return isHit;
}

When I call it, I get:

Error: CGContextSaveGState: invalid context 0x0
Error: CGContextAddPath: invalid context 0x0
Error: CGContextPathContainsPoint: invalid context 0x0
Error: CGContextRestoreGState: invalid context 0x0

Here's my view's drawRect function, and my code to create my path:

- (UIBezierPath *) createPath {
    static UIBezierPath *path = nil;
    if(!path) {
        path = [[UIBezierPath bezierPathWithOvalInRect:CGRectMake(35, 45, 250, 250)] retain];
        path.lineWidth = 50.0;
        [path closePath];
    }    
    return path;
}

/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
*/ 
- (void)drawRect:(CGRect)rect
{
    // Drawing code

    //draw a circle
    UIBezierPath *aPath = [self createPath];

    //set stroke width
    aPath.lineWidth = 50.0;

    //set stroke color
    [[UIColor blueColor] setStroke];

    //stroke path
    [aPath stroke];

    //close path
    [aPath closePath];

    //add a label at the "top"
    UILabel *topLabel;
    topLabel = [[UILabel alloc]initWithFrame:CGRectMake(120, -5, 80, 25)];
    topLabel.text = @"The Top";
    [self addSubview:topLabel];
}

I'm then trying to call the containsPoint function inside of touchesMoved, like this:

if (![self containsPoint:c onPath:[self createPath] inFillArea:NO]) return;

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

謌踐踏愛綪 2024-11-17 03:52:58

当您当前未绘图时(如在 touchesMoved 方法中),没有当前上下文,因此 UIGraphicsGetCurrentContext() 将返回 NULL。

由于您对上下文所做的只是使用其当前路径,因此您也可以使用 CGPathContainsPoint 而不是 CGContextPathContainsPoint

When you're currently not drawing (as in the touchesMoved method), there is no current context, so UIGraphicsGetCurrentContext() will return NULL.

As all you're doing with the context is to use its current path, you could just as well use CGPathContainsPoint instead of CGContextPathContainsPoint.

瞎闹 2024-11-17 03:52:58

Apple 的示例假设您正在图形上下文中工作。你不是,所以你可以在方法中添加两行:

UIGraphicsBeginImageContext(self.frame.size); // ADD THIS...
CGContextRef context = UIGraphicsGetCurrentContext(); // ...before this

CGContextRestoreGState(context); // after this...
UIGraphicsEndImageContext(); // ADD THIS

刚刚遇到了同样的问题,这为我解决了它!

Apple's example assumes you're working inside a graphics context. You're not, so you can just add two lines to the method:

UIGraphicsBeginImageContext(self.frame.size); // ADD THIS...
CGContextRef context = UIGraphicsGetCurrentContext(); // ...before this

and

CGContextRestoreGState(context); // after this...
UIGraphicsEndImageContext(); // ADD THIS

I just ran into the same problem, and this fixed it for me!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文