假设我们有两个UIBezierPaths,分别是path1和path2 ...(它们在运行时已相对于视图范围进行了定义,并且已作为同一视图的属性存在)。

我们想要获取一个类型为UIBezierPath的新路径,即path3,这是从path1中减去path2的结果:

ios - 如何从A中减去UIBezierPath A和B的交集?-LMLPHP

完成此操作的方式(如here所示)是这样做的:

path1.append(path2.reversing())

但是,这似乎仅在path1完全包含path2的情况下有效。

例如,考虑只有部分相交的情况-路径1不完全包含路径2。如果我们应用与上述相同的方法,则会发生这种情况:

ios - 如何从A中减去UIBezierPath A和B的交集?-LMLPHP

在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为绿色:

ios - 如何从A中减去UIBezierPath A和B的交集?-LMLPHP

可能性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。

看起来像这样:

ios - 如何从A中减去UIBezierPath A和B的交集?-LMLPHP

可能性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类别,因此将无提示地不加载框架并最终崩溃。

结果看起来像这样:

ios - 如何从A中减去UIBezierPath A和B的交集?-LMLPHP

因此,这实际上将提供您想要的结果,但是您将不得不使用3rd party库。

09-10 04:14