UIBelzierpath - path.contains(userTouchPoint) 只能检测 userTouchPoint.y 是否恰好位于路径 Y 位置
UIBelzierpath - path.contains(userTouchPoint) can only detect if userTouchPoint.y is exactly at path Y position
我有一个这样的路径(红色中间线),它是从
创建的
func drawALine(point1:CGPoint,point2:CGPoint)->CAShapeLayer{
let path = UIBezierPath()
path.move(to: point1)
path.addLine(to: point2)
let shapeLayer = CAShapeLayer()
shapeLayer.path = path.cgPath
shapeLayer.strokeColor = UIColor.red.cgColor
shapeLayer.lineWidth = 10
self.layer.addSublayer(shapeLayer)
return shapeLayer
}
因为我有多条线,所以我必须检测我接触的是哪一条线
for each in RulerModelArray{
if (!(each.midPath.path?.contains(touchPoint))!) {
print("not contain")
} else {
print("contained",each.ID)
}
}
问题是如果我的 point1
/point2
y 是 450,而我的 touchPoint.y 是 450.00001 那么它就不会被检测到。只有大约 1% 的地方我无法在完美的地方点击。
用这个测试:
let testPoint:CGPoint = CGPoint(x: touchPoint.x, y: touchPoint.y + 0.0001 )
for each in RulerModelArray{
if (!(each.midPath.contains(testPoint))) {
print("not contain")
} else {
print("contained",each.ID)
}
}
///always return not contain
我能检测到 shapeLayer.lineWidth = 10
内的路径吗?
你可以用这个
检查 CGPoint 是否在 UIBezierPath 的范围内
适用于水平线,因为水平线的尺寸高度为 0
extension UIBezierPath{
func hasForHorizontalLine(pt point: CGPoint) -> Bool{
let bezierRect = bounds
let origin = bezierRect.origin
let size = bezierRect.size
if origin.x <= point.x , origin.x + size.width >= point.x, origin.y - lineWidth * 0.5 <= point.y , origin.y + lineWidth * 0.5 >= point.y{
return true
}
else{
return false
}
}
}
这种方式更通用
适用于任何类型的直线,
通过计算触摸点到目标线的距离
extension CGPoint{
// tolerance, should by the lineWidth of a UIBezierPath
func contained(byStraightLine start: CGPoint,to end: CGPoint, tolerance width: CGFloat) -> Bool{
return distance(fromLine: start, to: end) <= width * 0.5
}
func distance(fromLine start: CGPoint,to end: CGPoint) -> CGFloat{
let a = end.y - start.y
let b = start.x - end.x
let c = (start.y - end.y) * start.x + ( end.x - start.x ) * start.y
return abs(a * x + b * y + c)/sqrt(a*a + b*b)
}
}
我有一个这样的路径(红色中间线),它是从
创建的 func drawALine(point1:CGPoint,point2:CGPoint)->CAShapeLayer{
let path = UIBezierPath()
path.move(to: point1)
path.addLine(to: point2)
let shapeLayer = CAShapeLayer()
shapeLayer.path = path.cgPath
shapeLayer.strokeColor = UIColor.red.cgColor
shapeLayer.lineWidth = 10
self.layer.addSublayer(shapeLayer)
return shapeLayer
}
因为我有多条线,所以我必须检测我接触的是哪一条线
for each in RulerModelArray{
if (!(each.midPath.path?.contains(touchPoint))!) {
print("not contain")
} else {
print("contained",each.ID)
}
}
问题是如果我的 point1
/point2
y 是 450,而我的 touchPoint.y 是 450.00001 那么它就不会被检测到。只有大约 1% 的地方我无法在完美的地方点击。
用这个测试:
let testPoint:CGPoint = CGPoint(x: touchPoint.x, y: touchPoint.y + 0.0001 )
for each in RulerModelArray{
if (!(each.midPath.contains(testPoint))) {
print("not contain")
} else {
print("contained",each.ID)
}
}
///always return not contain
我能检测到 shapeLayer.lineWidth = 10
内的路径吗?
你可以用这个
检查 CGPoint 是否在 UIBezierPath 的范围内
适用于水平线,因为水平线的尺寸高度为 0
extension UIBezierPath{
func hasForHorizontalLine(pt point: CGPoint) -> Bool{
let bezierRect = bounds
let origin = bezierRect.origin
let size = bezierRect.size
if origin.x <= point.x , origin.x + size.width >= point.x, origin.y - lineWidth * 0.5 <= point.y , origin.y + lineWidth * 0.5 >= point.y{
return true
}
else{
return false
}
}
}
这种方式更通用
适用于任何类型的直线,
通过计算触摸点到目标线的距离
extension CGPoint{
// tolerance, should by the lineWidth of a UIBezierPath
func contained(byStraightLine start: CGPoint,to end: CGPoint, tolerance width: CGFloat) -> Bool{
return distance(fromLine: start, to: end) <= width * 0.5
}
func distance(fromLine start: CGPoint,to end: CGPoint) -> CGFloat{
let a = end.y - start.y
let b = start.x - end.x
let c = (start.y - end.y) * start.x + ( end.x - start.x ) * start.y
return abs(a * x + b * y + c)/sqrt(a*a + b*b)
}
}