简体   繁体   English

如何在 UIImage 上“切”出一个透明孔?

[英]How can I 'cut' a transparent hole in a UIImage?

I'm trying to cut an transparent square in a UIImage, however I honestly have no idea where/how to start.我正在尝试在 UIImage 中切割一个透明正方形,但老实说,我不知道从哪里/如何开始。

Any help would be greatly appreciated.任何帮助将不胜感激。

Thanks!谢谢!

Presume that your image is being displayed in a view - probably a UIImageView.假设您的图像显示在视图中 - 可能是 UIImageView。 Then we can punch a rectangular hole in that view by masking the view's layer .然后我们可以通过屏蔽视图的图层在该视图中打一个矩形孔。 Every view has a layer.每个视图都有一个层。 We will apply to this view's layer a mask which is itself a layer containing an image, which we will generate in code.我们将在这个视图的图层上应用一个蒙版,它本身就是一个包含图像的图层,我们将在代码中生成它。 The image will be black except for a clear rectangle somewhere in the middle.除了中间某处的清晰矩形外,图像将是黑色的。 That clear rectangle will cause the hole in the image view.那个清晰的矩形将导致图像视图中出现孔洞。

So, let self.iv be this UIImageView.所以,让self.iv成为这个 UIImageView。 Try running this code:尝试运行此代码:

CGRect r = self.iv.bounds;
CGRect r2 = CGRectMake(20,20,40,40); // adjust this as desired!
UIGraphicsBeginImageContextWithOptions(r.size, NO, 0);
CGContextRef c = UIGraphicsGetCurrentContext();
CGContextAddRect(c, r2);
CGContextAddRect(c, r);
CGContextEOClip(c);
CGContextSetFillColorWithColor(c, [UIColor blackColor].CGColor);
CGContextFillRect(c, r);
UIImage* maskim = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
CALayer* mask = [CALayer layer];
mask.frame = r;
mask.contents = (id)maskim.CGImage;
self.iv.layer.mask = mask;

For example, in this image, the white square is not a superimposed square, it is a hole, showing the white of the window background behind it:例如,在这张图片中,白色方块不是叠加的方块,它是一个洞,显示了它后面的窗口背景的白色:

在此处输入图片说明

EDIT : I feel obligated, since I mentioned it in a comment, to show how to do the same thing with a CAShapeLayer.编辑:我觉得有义务,因为我在评论中提到过,展示如何用 CAShapeLayer 做同样的事情。 The result is exactly the same:结果完全一样:

CGRect r = self.iv.bounds;
CGRect r2 = CGRectMake(20,20,40,40); // adjust this as desired!
CAShapeLayer* lay = [CAShapeLayer layer];
CGMutablePathRef path = CGPathCreateMutable();
CGPathAddRect(path, nil, r2);
CGPathAddRect(path, nil, r);
lay.path = path;
CGPathRelease(path);
lay.fillRule = kCAFillRuleEvenOdd;
self.iv.layer.mask = lay;

Here's a simple Swift function cut#hole#inView to copy and paste for 2017这是一个简单的 Swift 函数cut#hole#inView用于复制和粘贴 2017

func cut(hole: CGRect, inView v: UIView) {
    let p:CGMutablePath = CGMutablePath()
    p.addRect(inView.bounds)
    p.addRect(hole)

    let s = CAShapeLayer()
    s.path = p
    s.fillRule = kCAFillRuleEvenOdd

    v.layer.mask = s
}

Just needed the Version from @Fattie, thanks again!只需要@Fattie 的版本,再次感谢! Here is the updated Code for Swift 5.1:这是 Swift 5.1 的更新代码:

private func cut(holeRect: CGRect, inView view: UIView) {
    let combinedPath = CGMutablePath()
    combinedPath.addRect(view.bounds)
    combinedPath.addRect(holeRect)

    let maskShape = CAShapeLayer()
    maskShape.path = combinedPath
    maskShape.fillRule = .evenOdd

    view.layer.mask = maskShape
}

If you want the cutout to have rounded corners you can replace combinedPath.addRect(holeRect) with rectanglePath.addRoundedRect(in: holeRect, cornerWidth: 8, cornerHeight: 8) .如果您希望切口具有圆角,您可以用rectanglePath.addRoundedRect(in: holeRect, cornerWidth: 8, cornerHeight: 8)替换combinedPath.addRect(holeRect) rectanglePath.addRoundedRect(in: holeRect, cornerWidth: 8, cornerHeight: 8)

Here's the updated code to cut a hole in an UIImage (instead of UIView) using Swift:下面是使用 Swift 在 UIImage(而不是 UIView)中挖一个洞的更新代码:

func cut(hole: CGRect, inView image: UIImage) -> UIImage? {
        UIGraphicsBeginImageContext(image.size)
        image.draw(at: CGPoint.zero)
        let context = UIGraphicsGetCurrentContext()!
        let bez = UIBezierPath(rect: hole)
        context.addPath(bez.cgPath)
        context.clip()
        context.clear(CGRect(x:0,y:0,width: image.size.width,height: image.size.height))
        let newImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        
        return newImage
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM