'In SwiftUI how can I clip a part of a view with another view?
I am trying to overlap two circles in SwiftUI and have a margin between them. I am presently using this method:
ZStack {
Circle()
.frame(width: 60, height: 60)
.foregroundColor(Color.blue)
.shadow(color: .black.opacity(0.5), radius: 4, x: 2, y: 2)
ZStack {
Circle()
.frame(width: 26, height: 26)
.foregroundColor(Color(.systemGray5))
Circle()
.frame(width: 22, height: 22)
.foregroundColor(.blue)
}
.offset(x: 26, y: 17)
}
The problem is that because of the shadow on the big circle I will never be able to perfectly match the background on the smaller circle's border circle (the one that is systemGray5. So although it looks okay, I only want the margin to appear between the circles. Not all the way around the smaller circle.
In illustrator or other ways I would clip the big image with my 26 size circle and it would look like a bite taken out of it. Then I can achieve this effect perfectly.
Is there anyway to clip the bottom of my large circle in SwiftUI?
Solution 1:[1]
Here is a demo of possible approach with inverted mask (it is simplified but the idea should be clear - removing hardcoding and "bite" position calculations is on you).
Tested with Xcode 13.2 / iOS 15.2
struct DemoView: View {
struct BiteCircle: Shape {
func path(in rect: CGRect) -> Path {
let offset = rect.maxX - 26
let crect = CGRect(origin: .zero, size: CGSize(width: 26, height: 26)).offsetBy(dx: offset, dy: offset)
var path = Rectangle().path(in: rect)
path.addPath(Circle().path(in: crect))
return path
}
}
var body: some View {
ZStack {
Circle()
.frame(width: 60, height: 60)
.foregroundColor(Color.blue)
.mask(BiteCircle().fill(style: .init(eoFill: true))) // << here !!
.shadow(color: .black.opacity(0.5), radius: 4, x: 2, y: 2)
Circle()
.frame(width: 22, height: 22)
.foregroundColor(.blue)
.offset(x: 18, y: 18)
}
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 |