英文:
How to use UIView as inverted mask for another UIView?
问题
应用一个 UIView
作为另一个 UIView
的蒙版没有问题。
let view = UIView(...)
let mask = UIView(...)
view.mask = mask
现在,只有在 mask
视图可见的地方,view
的部分才可见。但是,如何进行反转呢?我想要的是在 mask
不可见的地方,view
可见。我该如何做到这一点?
虽然我找到了几种反转路径蒙版(使用 CAShapeLayer
)或反转图像的解决方案,但这不是我想要的。我不想要反转路径蒙版或图像,而是想要反转视图蒙版。
假设 view
是一个红色矩形,而 mask
是一个绿色圆。将 mask
应用于 view
将导致一个红色圆。然而,我想创建一个带有圆形孔的红色矩形。
再次强调:创建一个圆形路径并将其应用为蒙版没有问题。我不是在寻找路径蒙版(反转或不反转),而是寻找一种使用任何 UIView
作为反转蒙版的解决方案。
这是否可能?
英文:
Applying a UIView
as mask to another UIView
is no problem.
let view = UIView(...)
let mask = UIView(...)
view.mask = mask
Now only those parts of view
will be visible where the mask
view is also visible. However, how can this be inverted? I would like view
to visible where mask
is NOT visible. How can I do this?
While I found several solutions to invert paths based masks (using CAShapeLayer
) or to invert images, this is not what I am looking for. I do not want to invert a path mask or an image but a view mask.
Assume the view
is a red rect and the mask
is a green circle. Applying the mask
to the view
would result in a red circle. However, I would like to create a red rect with a circle hole in it.
Again: Creating a circle path and applying it as mask is no problem. I am NOT looking for path masks (inverted or not) but for a solution to use any UIView as inverted mask.
Is this possible?
答案1
得分: 1
这有点取决于你对*"any UIView
"和"inverted"*的理解。
举个例子...如果这是anyView
:
Inverted 是什么意思?
假设你说的是一个带有透明背景的UIView
,其中包含一些子视图,可能还有一些形状等。
所以,如果我们设置一个带有大量大文本的标签,它将位于我们的视图后面:
然后添加一个我们想要遮罩的图像视图,即anyView
,以及另一个带有透明背景的anyView
的副本,以便我们能看到我们正在做什么:
我们可以将anyView
渲染到UIImage
(renderedImage
),然后使用单一颜色创建另一个UIImage
(可以是任何单一颜色,我在此示例中使用了.systemGreen
),然后使用blendMode: .destinationOut
渲染renderedImage
,得到这个:
然后我们将创建一个新的UIImageView
,并将其用作蒙版:
func mask(someView: UIView, withView: UIView) {
// 确保我们将用作蒙版的视图的背景是透明的
let bkgColor = withView.backgroundColor
withView.backgroundColor = .clear
let sz = withView.bounds.size
let renderer = UIGraphicsImageRenderer(size: sz)
let renderedImage = renderer.image { rendererContext in
withView.drawHierarchy(in: withView.bounds, afterScreenUpdates: true)
}
let invertedImage = renderer.image { rendererContext in
UIColor.systemGreen.setFill()
UIRectFill(.init(origin: .zero, size: renderedImage.size))
renderedImage.draw(at: .zero, blendMode: .destinationOut, alpha: 1.0)
}
tempImageView.image = invertedImage
// 创建一个新的图像视图用作蒙版
let newMaskView = UIImageView(frame: someView.bounds)
newMaskView.image = invertedImage
someView.mask = newMaskView
// 重置蒙版源视图的背景
withView.backgroundColor = bkgColor
}
得到这个结果:
英文:
This depends a bit on what you mean by "any UIView
" and "inverted".
For example... if this is anyView
:
What is inverted?
Let's assume that you're talking about a UIView
with a clear background, containing some subviews and maybe some shapes, etc.
So, if we setup a label with lots of large text that will be behind our views:
then add an image view that we want to mask, our anyView
, and another copy of anyView
with clear background so we can see what we're doing:
What we can do is render anyView
to a UIImage
(renderedImage
), then create another UIImage
with a solid color (can be any solid color, I used .systemGreen
for this example), and then render renderedImage
with blendMode: .destinationOut
, to get this:
Then we'll create a new UIImageView
with that image, and use that as the mask:
func mask(someView: UIView, withView: UIView) {
// make sure the background of the view we're going to use
// as the mask is clear
let bkgColor = withView.backgroundColor
withView.backgroundColor = .clear
let sz = withView.bounds.size
let renderer = UIGraphicsImageRenderer(size: sz)
let renderedImage = renderer.image { rendererContext in
withView.drawHierarchy(in: withView.bounds, afterScreenUpdates: true)
}
let invertedImage = renderer.image { rendererContext in
UIColor.systemGreen.setFill()
UIRectFill(.init(origin: .zero, size: renderedImage.size))
renderedImage.draw(at: .zero, blendMode: .destinationOut, alpha: 1.0)
}
tempImageView.image = invertedImage
// create a new image view to use as a mask
let newMaskView = UIImageView(frame: someView.bounds)
newMaskView.image = invertedImage
someView.mask = newMaskView
// reset the mask source view's background
withView.backgroundColor = bkgColor
}
giving us this result:
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论