Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SwiftUI, multiple shapes with unified shadow?

Is there a way in SwiftUI to union two shapes so that they cast a unified shadow. I have tried various combinations and modifiers but don't seem to be able to achieve the look I am after. Any insight would be much appreciated.

struct CardView: View {
    var body: some View {
        Group {
            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)
        }.shadow(color: Color.black, radius: 10, x: 0, y: 0)
    }
}

This is what I get, and what I am after ...

enter image description here

NOTE: zIndex was just something I tried, i.e. both shapes having the same zIndex etc. its also a quick way to reorder things without having to move the shapes within the container.

like image 326
fuzzygoat Avatar asked Dec 18 '22 13:12

fuzzygoat


2 Answers

Here is possible solution. Tested with Xcode 11.4 / iOS 13.4

demoenter image description here

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)
    }
}
like image 188
Asperi Avatar answered Jan 14 '23 12:01

Asperi


I think the correct answer is @Asperi's .compositingGroup as documented here (https://developer.apple.com/documentation/swiftui/group/3284789-compositinggroup) but 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:

enter image description here

The version above is not the best practice, but nevertheless, try to understand how shapes and cropping work, as in some use cases it might come useful.

like image 28
punkbit Avatar answered Jan 14 '23 13:01

punkbit