如何在 UIImage 中“切割”透明孔?

Posted

技术标签:

【中文标题】如何在 UIImage 中“切割”透明孔?【英文标题】:How can I 'cut' a transparent hole in a UIImage? 【发布时间】:2014-05-04 03:04:50 【问题描述】:

我正在尝试在 UIImage 中剪切一个透明的正方形,但是我真的不知道从哪里/如何开始。

任何帮助将不胜感激。

谢谢!

【问题讨论】:

你想在 image 中还是在显示它的 UIImageView 中切洞? 看看我如何在这段代码中的 UIImageView(及其图像)上打一个圆孔:***.com/a/8632731/341994 你会做的完全一样,只是你画的是正方形而不是圆形。 @matt:在实际的 UIImageView 上切一个洞实际上是完美的!除了,我不知道如何使用您链接的代码:p 什么是 CLayer 和 CGContextRef?谢谢!! 我很高兴您想了解这里的实际情况,而不是盲目地复制一堆代码。这是我关于如何在 ios 中绘制的全部解释,包括该代码中涉及的所有内容,除了实际的“屏蔽层”部分:apeth.com/iOSBook/ch15.html 这是我对层的讨论(您需要了解这一点,因为打孔涉及屏蔽视图层):apeth.com/iOSBook/ch16.html(尤其是apeth.com/iOSBook/ch16.html#_shadows_borders_and_more) @matt:我会仔细阅读这个,非常感谢!大量有用的信息 【参考方案1】:

假设您的图像正在视图中显示 - 可能是 UIImageView。然后我们可以通过屏蔽视图层在该视图中打一个矩形孔。每个视图都有一个层。我们将为这个视图的图层应用一个遮罩,该遮罩本身就是一个包含图像的图层,我们将在代码中生成该图像。除了中间某处的清晰矩形外,图像将是黑色的。那个清晰的矩形会在图像视图中造成洞。

所以,让self.iv 成为这个 UIImageView。尝试运行此代码:

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;

例如,在这张图片中,白色方块不是叠加的方块,它是一个洞,显示它后面的窗口背景的白色:

编辑:我觉得有义务,因为我在评论中提到它,展示如何用 CAShapeLayer 做同样的事情。结果完全一样:

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;

【讨论】:

这非常有效,非常感谢马特!我仍在阅读您链接的内容,但很高兴知道我有工作代码可供参考:D 再次感谢您,您太棒了! :) 真正酷的部分(其中之一)是它适用于 any UIView。你可以在任何东西上打一个洞。此外,您可以打一个半透明的孔,而不是打一个纯孔。此外,我们在这里所做的并不是唯一的方法。我们可以使用 CAShapeLayer 作为我们的蒙版,而不是制作图像。 这/是/很酷!如果我需要再次做这样的事情,我一定会记住这一点:D 编辑了我的答案以展示如何使用形状图层进行操作。开始时您可能会发现这更容易。另外(得到这个)一个形状层可以让你动画它显示的形状,所以我认为你可以移动或以其他方式以动画方式改变孔。 太酷了!是的,这更有意义,但是在所有这些“点击”之前我还有很多学习要做:P 再次感谢伙计! :D【参考方案2】:

这是一个简单的 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

【讨论】:

【参考方案3】:

只需要@Fattie 的版本,再次感谢!这是 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

如果您希望切口具有圆角,可以将combinedPath.addRect(holeRect) 替换为rectanglePath.addRoundedRect(in: holeRect, cornerWidth: 8, cornerHeight: 8)

【讨论】:

以上是关于如何在 UIImage 中“切割”透明孔?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 UIView 中制作透明孔

如何在不透明的 UIImage 上用另一种颜色替换给定颜色 [重复]

如何设置 UIImage 的不透明度/alpha?

如何检查 UIImage 是不是具有透明度

如何删除 UIImage 背景颜色并使其透明?

创建内部带有透明孔的小部件