反转CALayer蒙版

16

在这里输入图像描述我正在尝试使用CALayer作为遮罩UIView的内容,遮罩是一个复杂的png图像。如果我将该图像应用为view.layer.mask,我得到的结果与我想要的相反。 有没有一种方法可以反转CAlayer?这是我的代码:

layerMask = CALayer()
guard let layerMask = layerMask else { return }    
layerMask.contents = #imageLiteral(resourceName: "mask").cgImage
view.layer.mask = layerMask
// What I would like to to is
view.layer.mask = layerMask.inverse. // <---

我看过一些关于反转CAShapeLayers和可变路径的文章,但没有关于如何反转CALayer的内容。我可以在Photoshop中反转图像以使Alpha通道反转,但这样做的问题是我无法创建一个能适配所有屏幕尺寸的具有完全相同大小的图像。希望我的问题表述清楚了。


问题在于遮罩在关键窗口的中心具有固定大小。如果我在Photoshop中绘制“正确”的遮罩,我永远无法使该遮罩适用于所有屏幕尺寸。因此,我使用我的公司标志作为遮罩,需要将其从主视图中剪影出来。 - arvidurs
在Photoshop中反转您的遮罩。否则,您可以在代码中反转它,但为什么要选择Photoshop之外的方式呢? - Lefteris
好的,我的回答告诉你如何做。如果你从那个黑色三角形开始,你可以制作一个包含三角形的任意大小的图像,并将其转换为掩码,以实现你想要的效果。 - matt
好的!谢谢Matt。很抱歉对此一无所知,您能否更新您的回答并附上一些代码示例呢? - arvidurs
这是核心动画中更令人沮丧的限制之一。它只需要一个invertsMask属性来反转像素透明度的值,以解决这种情况。 - CIFilter
显示剩余3条评论
2个回答

8
我会构建实时口罩。如果您有标志的黑色图像,则很容易。使用标准技术,您可以将标志图像绘制到实时构建的图像中,因此您可以控制图像的大小以及其中标志的大小和位置。使用“蒙版转换为 Alpha” CIFilter,您可以将黑色转换为透明以用作图层蒙版。
所以,举个例子。这是背景图像:无论我们在前景中打洞穴,这就是我们想要看到的东西:

enter image description here

这是前景图像,位于背景之上并完全隐藏它:

enter image description here

这是黑色的Logo(忽略灰色,它代表透明度):

enter image description here

这是一个在正确尺寸的白色背景中用代码绘制的标志:

enter image description here

最后,这张图片被转换成掩码,并使用Mask To Alpha CIFilter附加到前景图像视图作为其mask

enter image description here

好的,我本可以选择一些更好的图片,但这是我手边有的。您可以看到,在标志中有黑色的地方,我们正在前景图像中打洞并查看背景图像,我认为这正是您想要做的。
关键步骤是最后一步,即将标志的黑白图像(im)转换为掩模; 这是我如何做到的:
    let cim = CIImage(image:im)
    let filter = CIFilter(name:"CIMaskToAlpha")!
    filter.setValue(cim, forKey: "inputImage")
    let out = filter.outputImage!
    let cgim = CIContext().createCGImage(out, from: out.extent)
    let lay = CALayer()
    lay.frame = self.iv.bounds
    lay.contents = cgim
    self.iv.layer.mask = lay

关键部分是将黑白图像转换为透明度掩码,我可以给你;等一下。 - matt
好的,我已经添加了最后一步的代码,这可能是你不知道如何完成的部分。 - matt
太好了!就是这样 :) 我在 C 中找到了类似的东西,但是一直在苦苦挣扎。再次感谢 Matt。 - arvidurs
12
伙计,你应该在那些变量命名中更加声明性。 - Ferico Samuel
@DuncanC 我没有说过这样的话。 - matt
显示剩余10条评论

6
如果您正在将CALayer用作另一个CALayer的蒙版,您可以通过创建一个大的不透明层并使用xor混合模式减去蒙版形状来反转蒙版。
例如,以下代码从大的不透明层中减去给定的层以创建一个蒙版层:
// Create a large opaque layer to serve as the inverted mask
let largeOpaqueLayer = CALayer()
largeOpaqueLayer.bounds = CGRect(x: -10_000_000, y: -10_000_000, width: 20_000_000, height: 20_000_000)
largeOpaqueLayer.backgroundColor = UIColor.black.cgColor

// Subtract out the mask shape using the `xor` blend mode
let maskLayer = ...
largeOpaqueLayer.addSublayer(maskLayer)
maskLayer.compositingFilter = "xor"

enter image description here

然后,您可以将该图层用作其他CALayermask。例如,在这里,我将其用作小蓝色矩形的掩码:

smallBlueRectangle.mask = largeOpaqueLayer

enter image description here

你可以看到遮罩是反转的!另一方面,如果你直接使用未反转的maskLayer作为mask,你会发现遮罩没有被反转:

enter image description here


2
很棒的回答。正是我在寻找的。 - Wizard
这个属性在iOS上支持吗?https://developer.apple.com/documentation/quartzcore/calayer/1410748-compositingfilter?language=objc还有奇怪的是,你将一个属性设置为字符串“xor” - 我们怎么知道可能的键是什么?(这对Objective-C有效吗?) - undefined

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