iOS:从UIBezierPath创建图像剪辑路径

3
我正在创建一个应用程序,允许用户剪切图像的一部分。为此,他们将创建大量UIBezierPaths以形成剪切路径。我的当前设置如下:
- 一个UIImageView显示他们正在剪切的图像。 - 在该UIImageView上方是UIImageView的自定义子类,执行自定义drawRect:方法以显示/更新用户添加的UIBezierPaths。 - 当用户点击“完成”按钮时,创建一个新的UIBezierPath对象,通过循环遍历它们存储在其中的数组并调用appendPath:来合并用户创建的所有单独路径。然后,这个新的UIBezierPath关闭了路径。
那就是我所做到的。我知道UIBezierPath有一个addClip方法,但我无法从文档中弄清楚如何使用它。
一般来说,所有我看到的剪辑示例都直接使用Core Graphics而不是UIBezierPath包装器。我意识到UIBezierPath有一个CGPath属性。所以,在剪辑时,我应该使用这个而不是完整的UIBezierPath对象吗?

1
你是如何检测要剪辑的部分的?通过手势吗? - Shrawan
1个回答

0

根据UIImageView类参考,苹果建议不要子类化UIImageView。感谢@rob mayoff指出这一点。

然而,如果您正在实现自己的drawRect,请从自己的UIView子类开始。并且,在drawRect中使用addClip。您可以使用UIBezierPath而无需将其转换为CGPath来完成此操作。

- (void)drawRect:(CGRect)rect
{
    // This assumes the clippingPath and image may be drawn in the current coordinate space.
    [[self clippingPath] addClip];
    [[self image] drawAtPoint:CGPointZero];
}

如果您想要按比例缩放以填充边界,您需要对图形上下文进行缩放。(您也可以将CGAffineTransform应用于剪切路径,但这是永久性的,因此您需要先复制剪切路径。)

- (void)drawRect:(CGRect)rect
{
    // This assumes the clippingPath and image are in the same coordinate space, and scales both to fill the view bounds.
    if ([self image])
    {
        CGSize imageSize = [[self image] size];
        CGRect bounds = [self bounds];

        CGContextRef context = UIGraphicsGetCurrentContext();
        CGContextScaleCTM(context, bounds.size.width/imageSize.width, bounds.size.height/imageSize.height);

        [[self clippingPath] addClip];
        [[self image] drawAtPoint:CGPointZero];
    }
}

这将在每个轴上分别缩放图像。如果您想保留其纵横比,您需要计算出整体缩放比例,并可能将其平移以使其居中或对齐。

最后,如果您的路径被频繁绘制,所有这些都相对较慢。您可能会发现将图像存储在CALayer中,并使用包含路径的CAShapeLayer进行遮罩处理会更快。 除测试外,请勿使用以下方法。您需要单独缩放图像层和遮罩层以使它们对齐。优点是可以更改遮罩而不会渲染底层图像。

- (void) setImage:(UIImage *)image;
{
    // This method should also store the image for later retrieval.
    // Putting an image directly into a CALayer will stretch the image to fill the layer.
    [[self layer] setContents:(id) [image CGImage]];
}

- (void) setClippingPath:(UIBezierPath *)clippingPath;
{
    // This method should also store the clippingPath for later retrieval.
    if (![[self layer] mask])
        [[self layer] setMask:[CAShapeLayer layer]];

    [(CAShapeLayer*) [[self layer] mask] setPath:[clippingPath CGPath]];
}

如果您成功地使用图层蒙版进行图像裁剪,那么您就不再需要drawRect方法了。为了提高效率,请将其删除。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接