SwiftUI: How to Add an Inverted Mask
SwiftUI's mask(alignment:_:)
method allows you to mask the view using the alpha channel of a given view. However, sometime you want to add an inverted mask. There are a few ways to achieve this depending on how your mask view is constructed.
Use eoFill
If your mask is a shape, you can create another shape by adding a Rectangle
path and applying a FillStyle(eoFill: true)
:
struct CircleInRectangle: Shape {
let padding: CGFloat
func path(in rect: CGRect) -> Path {
var shape = Rectangle().path(in: rect)
let paddedRect = rect.insetBy(dx: padding, dy: padding)
shape.addPath(Circle().path(in: paddedRect))
return shape
}
}
struct ContentView: View {
var body: some View {
Image(uiImage: #imageLiteral(resourceName: "img.jpeg"))
.resizable()
.scaledToFill()
.clipped()
.frame(width: 400, height: 225)
.background(.white)
.mask(
CircleInRectangle(padding: 24)
.fill(style: .init(eoFill: true))
)
)
}
}
Use .luminanceToAlpha()
SwiftUI's .luminanceToAlpha()
modifier creates a mask by making dark colors transparent and bright colors opaque.
struct ContentView: View {
var body: some View {
Image(uiImage: #imageLiteral(resourceName: "pattern.jpeg"))
.resizable()
.scaledToFill()
.clipped()
.frame(width: 400, height: 225)
.background(.white)
.mask(
Circle()
.padding()
.foregroundColor(.black)
.background(.white)
.compositingGroup()
.luminanceToAlpha()
)
}
}
Use .blendMode(.destinationOut)
SwiftUI's .blendMode(.destinationOut)
modifier allows you to erase any of the background that is covered by opaque source pixels.
struct ContentView: View {
var body: some View {
Image(uiImage: #imageLiteral(resourceName: "pattern.jpeg"))
.resizable()
.scaledToFill()
.clipped()
.frame(width: 400, height: 225)
.background(.white)
.mask(
Color.black
.overlay(
Circle()
.padding()
.blendMode(.destinationOut)
)
.compositingGroup()
)
}
}