SwiftUI add inverted mask
Here is a demo of possible approach of creating inverted mask, by SwiftUI only, (on example to make a hole in view)
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)))
}
}
Inverted mask swiftui with system image
This answer by Vlad Lego works when applied here.
You create your mask using .black
for the parts you want cut out, and .white
for the parts you want preserved.
(assuming the background is red, this is what it would look like)
Rectangle()
.foregroundColor(Color.white)
.mask(
ZStack {
Circle()
.fill(Color.white)
.frame(width: 50, height: 50)
Image(systemName: "play.fill")
.font(.system(size: 24))
.foregroundColor(Color.black)
}
.compositingGroup()
.luminanceToAlpha()
)
How to apply an inverse text mask in Swift?
Whilst not exactly the same, please refer to the answer provided here by Rob who answered a similar question:
How do I style a button to have transparent text?
This should get you started at the very least...
Using Swift and CAShapeLayer() with masking, how can I avoid inverting the mask when masked regions intersect?
You asked:
how can I avoid inverting the mask when masked regions intersect?
In short, do not use the .evenOdd
fill rule.
You have specified a fillRule
of .evenOdd
. That results in intersections of paths to invert. Here is a red colored view with a mask consisting of a path with two overlapping circular arcs with the .evenOdd
rule:
If you use .nonZero
(which, coincidentally, is the default fill rule for shape layers), they will not invert each other:
E.g.
class ViewController: UIViewController {
@IBOutlet weak var imageView: UIImageView!
var maskLayer: CAShapeLayer = {
let shapeLayer = CAShapeLayer()
shapeLayer.fillColor = UIColor.white.cgColor
return shapeLayer
}()
var points: [CGPoint] = [] // this isn't strictly necessary, but just in case you want an array of the points that were tapped
var path = UIBezierPath()
override func viewDidLoad() {
super.viewDidLoad()
imageView.layer.mask = maskLayer
}
@IBAction func handleTapGesture(_ gesture: UITapGestureRecognizer) {
let point = gesture.location(in: gesture.view)
points.append(point)
path.move(to: point)
path.addArc(withCenter: point, radius: 40, startAngle: 0, endAngle: .pi * 2, clockwise: true)
maskLayer.path = path.cgPath
}
}
Resulting in:
SwiftUI Mask a rectangle inside a rounded rectangle
If I correctly understood your goal, here is a solution - the only needed clip in right place is after internal content (two rectangles in this case) is constructed. So clipping with RoundedRectangle
gives rounded corners around entire card. (As well as shadow
most probably is needed to entire card, so placed at the end).
UPDATE: re-tested with Xcode 13.3 / iOS 15.4
ZStack (alignment: .topLeading) {
Rectangle()
.foregroundColor(.white)
Rectangle()
.fill(Color.pink)
.frame(minWidth: 0, maxWidth: .infinity, maxHeight: 150, alignment: .top)
}
.clipShape(RoundedRectangle(cornerRadius: 16)) // << here !!
.frame(width: 300, height: 450, alignment: .center)
.shadow(radius: 10)
How can I mask a UIImageView?
There's an easier way.
#import <QuartzCore/QuartzCore.h>
// remember to include Framework as well
CALayer *mask = [CALayer layer];
mask.contents = (id)[[UIImage imageNamed:@"mask.png"] CGImage];
mask.frame = CGRectMake(0, 0, <img_width>, <img_height>);
yourImageView.layer.mask = mask;
yourImageView.layer.masksToBounds = YES;
For Swift 4 and plus follow code below
let mask = CALayer()
mask.contents = [ UIImage(named: "right_challenge_bg")?.cgImage] as Any
mask.frame = CGRect(x: 0, y: 0, width: leftBGImage.frame.size.width, height: leftBGImage.frame.size.height)
leftBGImage.layer.mask = mask
leftBGImage.layer.masksToBounds = true
Related Topics
Swift Firebase Must Be a Non-Empty String and Not Contain '.' '#' '$' '[' or ']'
Best Way to Make Amazon Aws Dynamodb Queries Using Swift
In Swift, How to Cast to Protocol with Associated Type
Self' Used Before All Stored Properties Are Initialized
What Are the Supported Swift String Format Specifiers
Understanding Swift 2.2 Selector Syntax - #Selector()
What Are "Intervals" in Swift Ranges
Extension May Not Contain Stored Property But Why Is Static Allowed
Swiftui: Global Overlay That Can Be Triggered from Any View
Uifont' Is Not Convertible to 'Uifont'
How to Include .Swift File from Other .Swift File in an Immediate Mode
Closure Use of Non-Escaping Parameter May Allow It to Escape
Scrollview + Navigationview Animation Glitch Swiftui
Objective-C Bridging Header for Frameworks
Swiftui. How to Change the Placeholder Color of the Textfield