How to get the distance to a CGPath for hit-testing?
我有一个开放的CGPath / UIBezierPath,我想为其检测用户是否触摸了它,即一个点是否在距路径一定距离内。 路径是开放的(即线/曲线,而不是形状)。 它可以包含直线和弯曲元素。 我如何获得到路径的距离以进行测试?
似乎CGPath / UIBezierPath都没有执行此操作的功能。 编辑:根据@nielsbot的建议,您可以使用
但是,我找到了一种很好的方法来实现我的最初目标,对路径进行了测试:
1 2 3 4 5 6 7 | - (BOOL)isPoint:(CGPoint)p withinDistance:(CGFloat)distance ofPath:(CGPathRef)path { CGPathRef hitPath = CGPathCreateCopyByStrokingPath(path, NULL, distance*2, kCGLineCapRound, kCGLineJoinRound, 0); BOOL isWithinDistance = CGPathContainsPoint(hitPath, NULL, p, false); CGPathRelease(hitPath); return isWithinDistance; } |
为了获得更好的性能,您可以缓存hitPath。 通过使用
对于迅速3.0:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | final func isPoint(point: CGPoint, withinDistance distance: CGFloat, ofPath path: CGPath) -> Bool { if let hitPath = CGPath( __byStroking: path, transform: nil, lineWidth: distance, lineCap: CGLineCap.round, lineJoin: CGLineJoin.miter, miterLimit: 0) { let isWithinDistance = hitPath.contains(point) return isWithinDistance } return false } |
用:
1 2 | let inside = self.isPoint(point: location, withinDistance: 4, ofPath: myPath!) if inside{... |
当然,正如Patrick所言,最好缓存hitPath,而不是每次都创建它。 如果您有UIBezierPath,只需:
1 | let inside = self.isPoint(point: location, withinDistance: 4, ofPath: myUIPath.cgPath!) |