假设我们有两个UIBezierPaths,分别是path1和path2 ...(它们在运行时已相对于视图范围进行了定义,并且已作为同一视图的属性存在)。
我们想要获取一个类型为UIBezierPath的新路径,即path3,这是从path1中减去path2的结果:
完成此操作的方式(如here所示)是这样做的:
path1.append(path2.reversing())
但是,这似乎仅在path1完全包含path2的情况下有效。
例如,考虑只有部分相交的情况-路径1不完全包含路径2。如果我们应用与上述相同的方法,则会发生这种情况:
在Android中,答案是:
path1.op(path2, Path.Op.DIFFERENCE);
那么... IOS中是否有等效的简单操作?
如果没有,是否存在可以写为的函数:
func returnPath2CutOutOfPath1(path1: UIBezierPath, path2: UiBezierPath) -> UIBezierPath {
// the mystery lies within these here parts. :)
}
最佳答案
没有直接的方法可以将UIBezierPaths的差异作为iOS上的新路径。
测试用例
private func path2() -> UIBezierPath {
return UIBezierPath(rect: CGRect(x: 100, y: 50, width: 200, height: 200))
}
private func path1() -> UIBezierPath {
return UIBezierPath(rect: CGRect(x: 50, y: 100, width: 200, height: 200))
}
起点:仅显示哪个路径代表什么:路径1为黄色,路径2为绿色:
可能性1
您可能已经看到了这种可能性:在问题中提到的链接中,如果只需要执行填充操作,则还有一个聪明的解决方案。
代码是从这个答案(通过您发布的链接)https://stackoverflow.com/a/8860341中获取的-仅转换为Swift:
func fillDifference(path2: UIBezierPath, path1: UIBezierPath) {
let clipPath = UIBezierPath.init(rect: .infinite)
clipPath.append(path2)
clipPath.usesEvenOddFillRule = true
UIGraphicsGetCurrentContext()?.saveGState()
clipPath.addClip()
path1.fill()
UIGraphicsGetCurrentContext()?.restoreGState()
}
因此,这将填充路径,但不会返回UIBezierPath,这意味着您无法应用轮廓,背景,轮廓宽度等,因为结果不是UIBezierPath。
看起来像这样:
可能性2
您可以使用第三方库,例如一位来自名为Adam Wulf的作者的文章:https://github.com/adamwulf/ClippingBezier。
该库是用Objective-C编写的,但可以从Swift调用。
在Swift中,它看起来像这样:
override func draw(_ rect: CGRect) {
let result = self.path1().difference(with: self.path2())
for p in result ?? [] {
p.stroke()
}
}
如果要使用此库,则必须注意一个小提示:如自述文件所述,在项目设置的“其他链接器标志”中,必须添加“-ObjC++ -lstdc ++”,否则将在没有抱怨的情况下进行构建,但是由于找不到UIBEzierPath类别,因此将无提示地不加载框架并最终崩溃。
结果看起来像这样:
因此,这实际上将提供您想要的结果,但是您将不得不使用3rd party库。