Skip to content

Instantly share code, notes, and snippets.

@nkmrh
Last active January 14, 2023 00:41
Show Gist options
  • Save nkmrh/4e35108f1253343082c62c17fbdc6853 to your computer and use it in GitHub Desktop.
Save nkmrh/4e35108f1253343082c62c17fbdc6853 to your computer and use it in GitHub Desktop.
Draw donut pie chart with SwiftUI
import UIKit
import SwiftUI
extension FloatingPoint {
var degreesToRadians: Self { self * .pi / 180 }
var radiansToDegrees: Self { self * 180 / .pi }
}
struct Donut: Identifiable {
var id = UUID()
var startValue: Float
var endValue: Float
var color: Color
}
struct ScaledArcBezier: Shape {
let startValue: Float
let endValue: Float
static func makeArcPath(startAngle: Float, endAngle: Float) -> UIBezierPath {
UIBezierPath(arcCenter: CGPoint(x: 0.5, y: 0.5),
radius: 0.5,
startAngle: CGFloat(startAngle.degreesToRadians),
endAngle: CGFloat(endAngle.degreesToRadians),
clockwise: true)
}
func path(in rect: CGRect) -> Path {
let startAngle = 360.0 * startValue
let endAngle = 360.0 * endValue
let path = Path(Self.makeArcPath(startAngle: startAngle, endAngle: endAngle).cgPath)
let multiplier = min(rect.width, rect.height)
return path
.applying(CGAffineTransform(scaleX: multiplier, y: multiplier))
.applying(CGAffineTransform(translationX: rect.midX, y: rect.midY).inverted())
.applying(CGAffineTransform(rotationAngle: CGFloat(90.0.degreesToRadians)).inverted())
.applying(CGAffineTransform(translationX: rect.midX, y: rect.midY))
}
}
struct ContentView: View {
let dounuts: [Donut]
var body: some View {
ZStack {
ForEach(dounuts, id: \.id) { donut in
ScaledArcBezier(startValue: donut.startValue, endValue: donut.endValue)
.stroke(style: StrokeStyle(lineWidth: 14, lineCap: .round, lineJoin: .round, miterLimit: 0, dash: [], dashPhase: 0))
.foregroundColor(donut.color)
}
}
.frame(width: 100, height: 100)
}
}
import PlaygroundSupport
PlaygroundPage.current.liveView = UIHostingController(
rootView: ContentView(
dounuts: [
Donut(startValue: 0, endValue: 1, color: Color.gray.opacity(0.5)),
Donut(startValue: 0, endValue: 0.27, color: Color.green.opacity(0.5)),
Donut(startValue: 0.28, endValue: 0.4, color: Color.purple.opacity(0.5))
]
)
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment