Search code examples
iosswiftgradientswiftui

How to add shadow to SwiftUI arc?


I have the following arc:

struct Arc : Shape
{
    @Binding var endAngle: Double
    var center: CGPoint
    var radius: CGFloat
    func path(in rect: CGRect) -> Path
    {
        var path = Path()

        path.addArc(center: center, radius: radius, startAngle: .degrees(270), endAngle: .degrees(endAngle), clockwise: false)

        return path.strokedPath(.init(lineWidth: 50, lineCap: .round))
    }
}

How can I add shadow, similar to the activity arcs on Apple Watch, such that at full circle the endAngle is still discernible?

EDIT: There's the additional issue at 360+ degrees (so full circle), that both arc ends get combined and are shown as a radial line (I see this because I've a applied an AngularGradient). Of course Arc won't do advanced things like continuing above the startAngle position, like the Apple Watch arcs do. But this was what I was looking for. Does anyone know how to do that in SwiftUI?


Solution

  • enter image description here

    what about this? ok...bit "tricky"

    import SwiftUI
    
        struct Arc: Shape {
        
        @Binding var startAngle: Double
        @Binding var endAngle: Double
        
        var center: CGPoint
        var radius: CGFloat
        var color: Color
        
        func path(in rect: CGRect) -> Path {
            var path = Path()
            
            let cgPath = CGMutablePath()
            cgPath.addArc(center: CGPoint(x: rect.midX, y: rect.midY), radius: radius, startAngle: CGFloat(startAngle), endAngle: CGFloat(endAngle), clockwise: true)
            
          //  path.addArc(center: center, radius: radius, startAngle: .degrees(270), endAngle: .degrees(endAngle), clockwise: false)
        
            path = Path(cgPath)
            
            return path.strokedPath(.init(lineWidth: 50, lineCap: .round))
        }
    }
    
    struct ContentView: View {
        var body: some View {
            ZStack() {
           //     Arc(endAngle: .constant(269), center: CGPoint(x: 200, y: 200), radius: 150, color: .red).foregroundColor(.red).opacity(0.2)
                Arc(startAngle: .constant(80 + 271), endAngle: .constant(80 + 271 + 340), center: CGPoint(x: 205, y: 205), radius: 150, color: .red).foregroundColor(.red)//.shadow(color: .black, radius: 5, x: -30, y: -170)
                Arc(startAngle: .constant(90), endAngle: .constant(80 + 270), center: CGPoint(x: 200, y: 200), radius: 150, color: .red).foregroundColor(.red).shadow(color: .black, radius: 5, x: -114, y: -230)
            }
             .background(Color.black)
        }
    }
    
    struct ContentView_Previews: PreviewProvider {
        static var previews: some View {
            ContentView()
        }
    }