Search code examples
swiftswiftuiviewgeometry

Get a Small Circle at Trim's Fill Value in SwiftUI


I have a circle which I am trimming to my given fill value. I want to have another small circle at the end of that trim's fill value.

I have made a circle with fill value like this:

my circle

And my code for this is:

struct CountdownView: View {
  
  @State var fillValue: CGFloat = 0.7

  var body: some View {

      ZStack {
            Circle()
                .foregroundColor(.white)
                .shadow(radius: 0.5)
            
            Circle()
                .trim(from: 0, to: fillValue)
                .stroke(Color.blue, style: .init(lineWidth: 6))
                .rotationEffect(.degrees(90))

        }
        .frame(width: 250, height: 250)
        .padding()

  }
}

I want to have another small circle at the end of the fillValue. This is my required view:

desired circle

How can I add this small circle at the end?


Solution

  • I added a small indicator circle which is offset to the right and then rotated so its centre is at the end of the stroke:

    struct ContentView: View {
        
        @State var fillValue: CGFloat = 0.7
        private let lineWidth = 6.0
        private let indicatorRadius = 6.0
        private let radius = 125.0
        
        var body: some View {
            ZStack {
                Circle()
                    .foregroundColor(.white)
                    .shadow(radius: 0.5)
                        
                Circle()
                    .trim(from: 0, to: fillValue)
                    .stroke(Color.blue, style: .init(lineWidth: lineWidth))
                    .rotationEffect(.degrees( 
                
                Circle()
                    .foregroundColor(.blue)
                    .frame(width: indicatorRadius * 2, height: indicatorRadius * 2)
                    .offset(x: radius, y: 0)
                    .rotationEffect(.degrees(90.0 + 360.0 * fillValue ))
            }
            .frame(width: radius * 2, height: radius * 2)
            .padding()
        }
    }
    

    image