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

时间:2011-07-28 14:52:13

标签: ios cocoa-touch drawing clipping uibezierpath

我正在创建一个允许用户剪切部分图片的应用。为了做到这一点,他们将创建一堆UIBezierPaths来形成剪切路径。我目前的设置如下:

  • UIImageView显示他们正在剪切的图像。
  • 上面说UIImageView是UIImageView的自定义子类 执行自定义drawRect:方法来显示/更新 用户正在添加的UIBezierPath。
  • 当用户单击“完成”按钮时,会创建一个新的UIBezierPath对象,该对象包含用户创建的所有单独路径,方法是循环存储它们并在其自身上调用appendPath:。然后,这个新的UIBezierPath将关闭它的路径。

就我而言。我知道UIBezierPath有一个addClip方法,但我无法从文档中找出如何使用它。

一般来说,我看到的所有剪切示例都直接使用Core Graphics而不是UIBezierPath包装器。我意识到UIBezierPath有一个CGPath属性。那么我应该在剪辑时使用它而不是完整的UIBezierPath对象吗?

1 个答案:

答案 0 :(得分:0)

根据{{​​3}},Apple说不要继承UIImageView的子类。感谢@rob mayoff指出这一点。

但是,如果您正在实现自己的drawRect,请从您自己的UIView子类开始。并且,使用addClip在drawRect中。您可以使用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应用于clippingPath,但这是永久性的,因此您需要先复制clippingPath。)

- (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中更快,UIImageView class reference包含路径的mask除测试外,请勿使用以下方法。您需要单独缩放图像层和蒙版以使它们对齐。优点是您可以在不渲染基础图像的情况下更改蒙版。

- (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方法。将其移除以提高效率。