UIBezierPath减去路径 [英] UIBezierPath Subtract Path

查看:135
本文介绍了UIBezierPath减去路径的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

通过使用 [UIBezierPath bezierPathWithRoundedRect:byRoundingCorners:cornerRadii:] ,我可以创建一个圆角视图,例如:

By using [UIBezierPath bezierPathWithRoundedRect:byRoundingCorners:cornerRadii:], I am able to create a rounded view, such as this:

如何我可以从这个路径中减去另一条路径(或其他方式),以创建这样的路径:

How could I subtract another path from this one (or some other way), to create a path like this:

我有什么方法可以做这样的事情吗?
Pseudocode:

Is there any way I can do something like this? Pseudocode:

UIBezierPath *bigMaskPath = [UIBezierPath bezierPathWithRoundedRect:bigView.bounds 
                                 byRoundingCorners:(UIRectCornerTopLeft|UIRectCornerTopRight)
                                       cornerRadii:CGSizeMake(18, 18)];
UIBezierPath *smallMaskPath = [UIBezierPath bezierPathWithRoundedRect:smalLView.bounds 
                                     byRoundingCorners:(UIRectCornerTopLeft|UIRectCornerTopRight)
                                           cornerRadii:CGSizeMake(18, 18)];

UIBezierPath *finalPath = [UIBezierPath pathBySubtractingPath:smallMaskPath fromPath:bigMaskPath];


推荐答案

如果你想划分减去的路径,你是靠自己。 Apple没有提供返回(或只是描边)从一个路径减去另一个路径的API。

If you want to stroke the subtracted path, you are on your own. Apple doesn't provide an API that returns (or just strokes) the subtraction of one path from another.

如果你只想填充减去的路径(如在你的路径中)示例图像),您可以使用剪切路径来完成。但是你必须使用一个技巧。向剪切路径添加路径时,新剪切路径是旧剪切路径和添加路径的交叉点。因此,如果您只是将 smallMaskPath 添加到剪切路径,您将最终只填充 smallMaskPath 中的区域,这是与你想要的相反。

If you just want to fill the subtracted path (as in your example image), you can do it using the clipping path. You have to use a trick, though. When you add a path to the clipping path, the new clipping path is the intersection of the old clipping path and the added path. So if you just add smallMaskPath to the clipping path, you will end up filling only the region inside smallMaskPath, which is the opposite of what you want.

你需要做的是将现有的剪切路径与相交smallMaskPath 。幸运的是,你可以使用偶数奇数绕组规则很容易地做到这一点。您可以在 Quartz 2D编程指南

What you need to do is intersect the existing clipping path with the inverse of smallMaskPath. Fortunately, you can do that pretty easily using the even-odd winding rule. You can read about the even-odd rule in the Quartz 2D Programming Guide.

基本思路是我们创建一个化合物带有两个子路径的路径:你的 smallMaskPath 和一个巨大的矩形,它完全包含你的 smallMaskPath 以及你可能想要的每个其他像素填。由于偶数规则, smallMaskPath 中的每个像素都将被视为复合路径之外,并且 smallMaskPath之外的每个像素将被视为复合路径的内部。

The basic idea is that we create a compound path with two subpaths: your smallMaskPath and a huge rectangle that completely encloses your smallMaskPath and every other pixel you might want to fill. Because of the even-odd rule, every pixel inside of smallMaskPath will be treated as outside of the compound path, and every pixel outside of smallMaskPath will be treated as inside of the compound path.

所以让我们创建这个复合路径。我们将从巨大的矩形开始。并且没有比无限矩形更大的矩形:

So let's create this compound path. We'll start with the huge rectangle. And there is no rectangle more huge than the infinite rectangle:

UIBezierPath *clipPath = [UIBezierPath bezierPathWithRect:CGRectInfinite];

现在我们通过添加 smallMaskPath to it:

Now we make it into a compound path by adding smallMaskPath to it:

[clipPath appendPath:smallMaskPath];

接下来我们设置使用偶数规则的路径:

Next we set the path to use the even-odd rule:

clipPath.usesEvenOddFillRule = YES;

在剪切到此路径之前,我们应该保存图形状态,以便我们可以撤消对我们完成时的剪切路径:

Before we clip to this path, we should save the graphics state so that we can undo the change to the clipping path when we're done:

CGContextSaveGState(UIGraphicsGetCurrentContext()); {

现在我们可以修改剪切路径:

Now we can modify the clipping path:

    [clipPath addClip];

我们可以填写 bigMaskPath

    [[UIColor orangeColor] setFill];
    [bigMaskPath fill];

最后我们恢复图形状态,撤消对剪切路径的更改:

Finally we restore the graphics state, undoing the change to the clipping path:

} CGContextRestoreGState(UIGraphicsGetCurrentContext());

如果你想复制/粘贴代码,这里是代码:

Here's the code all together in case you want to copy/paste it:

UIBezierPath *clipPath = [UIBezierPath bezierPathWithRect:CGRectInfinite];
[clipPath appendPath:smallMaskPath];
clipPath.usesEvenOddFillRule = YES;

CGContextSaveGState(UIGraphicsGetCurrentContext()); {
    [clipPath addClip];
    [[UIColor orangeColor] setFill];
    [bigMaskPath fill];
} CGContextRestoreGState(UIGraphicsGetCurrentContext());

这篇关于UIBezierPath减去路径的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆