Skip to content

Instantly share code, notes, and snippets.

@mykolaharmash
Created August 9, 2025 11:42
Show Gist options
  • Select an option

  • Save mykolaharmash/7f37b80fe95c8cd1d2d2857dcbe551dc to your computer and use it in GitHub Desktop.

Select an option

Save mykolaharmash/7f37b80fe95c8cd1d2d2857dcbe551dc to your computer and use it in GitHub Desktop.
//
// CircularProgressBarView.swift
// FastingTimer
//
// Created by Mykola Harmash on 09.08.25.
//
import SwiftUI
struct CircularProgressBarView: View {
let value: Double
let startColor: Color
let endColor: Color
var body: some View {
Circle()
.stroke(Color(uiColor: .systemGray5), lineWidth: 18)
.overlay {
GeometryReader { container in
Circle()
.fill(startColor)
.frame(width: 16)
.position(x: container.size.height / 2, y: 0)
}
}
.overlay {
let valueOverlap = max(value - 1.0, 0.0)
Circle()
.trim(from: 0, to: value)
.stroke(
AngularGradient(
colors: [startColor, endColor],
center: .center,
angle: .degrees(360 * valueOverlap)
),
style: .init(lineWidth: 16)
)
.rotationEffect(.degrees(-90))
}
.overlay {
GeometryReader { container in
let angle = Double.pi * 2 * value - (Double.pi / 2)
let x = cos(angle) * container.size.width / 2 + container.size.width / 2
let y = sin(angle) * container.size.height / 2 + container.size.height / 2
Circle()
.fill(startColor.mix(with: endColor, by: min(value, 1.0) - 0.05))
.frame(width: 16)
.position(x: x, y: y)
}
}
}
}
#Preview {
@Previewable @State var value: Double = 0.0
VStack {
CircularProgressBarView(
value: value,
startColor: .blue,
endColor: .cyan.mix(with: .white, by: 0.5)
)
.frame(width: 100, height: 100)
Slider(value: $value, in: 0...3, step: 0.1)
.padding(60)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment