我正在尝试为两个形状添加遮罩,以便第二个形状遮住第一个形状。如果我执行类似的操作Circle().mask(Circle().offset(…))
,则会产生相反的效果:防止第一个圆圈外的任何内容可见。
对于UIView
答案就在这里:在drawRect中的iOS转化面具
然而,试图实现这SwiftUI没有 UIView
躲开我。我尝试实现一个 InvertedShape,然后我可以将其用作掩码:
struct InvertedShape<OriginalType: Shape>: Shape {
let originalShape: OriginalType
func path(in rect: CGRect) -> Path {
let mutableOriginal = originalShape.path(in: rect).cgPath.mutableCopy()!
mutableOriginal.addPath(Path(rect).cgPath)
return Path(mutableOriginal)
.evenOddFillRule()
}
}
Run Code Online (Sandbox Code Playgroud)
不幸的是,SwiftUI 路径没有addPath(Path)
(因为它们是不可变的)或evenOddFillRule()
. 您可以访问路径的 CGPath 并制作可变副本,然后添加两个路径,但是,evenOddFillRule
需要CGLayer
在CGPath
.而不是. 所以除非我能到达 CGLayer,否则我不确定如何继续。
这是斯威夫特 5。
Ser*_*kov 23
使用.blendMode修饰符
ZStack {
Rectangle() // destination
Circle() // source
.blendMode(.destinationOut)
}
.compositingGroup()
Run Code Online (Sandbox Code Playgroud)
Asp*_*eri 22
这是仅通过 SwiftUI 创建倒置遮罩的可能方法的演示(例如在视图中打孔)
func HoleShapeMask(in rect: CGRect) -> Path {
var shape = Rectangle().path(in: rect)
shape.addPath(Circle().path(in: rect))
return shape
}
struct TestInvertedMask: View {
let rect = CGRect(x: 0, y: 0, width: 300, height: 100)
var body: some View {
Rectangle()
.fill(Color.blue)
.frame(width: rect.width, height: rect.height)
.mask(HoleShapeMask(in: rect).fill(style: FillStyle(eoFill: true)))
}
}
Run Code Online (Sandbox Code Playgroud)
Vla*_*ego 14
这是另一种方法,它更 Swiftly。
诀窍是使用:
YourMaskView()
.compositingGroup()
.luminanceToAlpha()
Run Code Online (Sandbox Code Playgroud)
maskedView.mask(YourMaskView())
只需创建具有黑白形状的蒙版,黑色将是透明的,白色是不透明的,介于两者之间的任何东西都将是半透明的。
.compositingView()
,类似于.drawingGroup()
,栅格化视图(将其转换为位图纹理)。顺便说一句,当您.blur
或执行任何其他像素级操作时,也会发生这种情况。
.luminanceToAlpha()
获取 RGB 亮度级别(我猜是通过平均 RGB 值),并将它们映射到位图的 Alpha(不透明度)通道。
Tam*_*gel 10
根据本文,.reverseMask
您可以使用以下修饰符来代替.mask
. 我修改了它以支持 iOS 13 及更高版本。
extension View {
@inlinable func reverseMask<Mask: View>(
alignment: Alignment = .center,
@ViewBuilder _ mask: () -> Mask
) -> some View {
self.mask(
ZStack {
Rectangle()
mask()
.blendMode(.destinationOut)
}
)
}
}
Run Code Online (Sandbox Code Playgroud)
用法:
ViewToMask()
.reverseMask {
MaskView()
}
Run Code Online (Sandbox Code Playgroud)
在接受的答案中使用掩码是一种很好的方法。不幸的是,掩码不会影响命中测试。可以通过以下方式制作带孔的形状。
extension Path {
var reversed: Path {
let reversedCGPath = UIBezierPath(cgPath: cgPath)
.reversing()
.cgPath
return Path(reversedCGPath)
}
}
struct ShapeWithHole: Shape {
func path(in rect: CGRect) -> Path {
var path = Rectangle().path(in: rect)
let hole = Circle().path(in: rect).reversed
path.addPath(hole)
return path
}
}
Run Code Online (Sandbox Code Playgroud)
诀窍是反转孔的路径。不幸的Path
是(还)不支持开箱即用的反转路径,因此扩展(使用UIBezierPath
)。然后该形状可用于剪辑和命中测试目的:
struct MaskedView: View {
var body: some View {
Rectangle()
.fill(Color.blue)
.frame(width: 300, height: 100)
.clipShape(ShapeWithHole()) // clips or masks the view
.contentShape(ShapeWithHole()) // needed for hit-testing
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
5508 次 |
最近记录: |