Create a single shadow for multiple shapes in SwiftUI
A user put a question about how to solve replacing multiple shape shadows, with a single uniform shadow for multiple shapes? He posted the initial implementation that caused a shadow to appear between shapes:
A good option is .compositingGroup as documented here
but
before I put that out, I’d like to leave a different working version because there are some use cases where you may not be able or want to use compositingGroup
.
So let’s look at .background, you can copy and paste the code to see in the simulator:
import SwiftUI
struct AnyShapedView: View {
var body: some View {
ZStack {
RoundedRectangle(cornerRadius: 20)
.fill(Color.orange)
.frame(width: 200, height: 250)
.zIndex(0)
Circle()
.trim(from: 0.5, to: 1)
.fill(Color.orange)
.frame(width: 100, height: 100)
.offset(y: -125)
.zIndex(1)
}
}
}
struct ContentView: View {
var body: some View {
AnyShapedView()
.background(
AnyShapedView()
.shadow(color: Color.black, radius: 10, x: 0, y: 0)
)
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
The output:
The solution by using the modifier compositingGroup
that makes compositing effects in this view’s ancestor views, like opacity and the blend mode, take effect before this view renders. Follows:
struct CardView: View {
var body: some View {
VStack(spacing: 0) {
Circle()
.trim(from: 0.5, to: 1)
.fill(Color.orange)
.frame(width: 100, height: 100)
.offset(x: 0, y: 50)
RoundedRectangle(cornerRadius: 20)
.fill(Color.orange)
.frame(width: 200, height: 250)
}
.compositingGroup()
.shadow(color: Color.primary, radius: 10, x: 0, y: 0)
}
}
The first should allow you to understand how to workout a solution given the background
modifier, and the compositingGroup
hopefully the quickest
way to solve a big percentage of cases you’d encounter.