Skip to content

Commit 5ca7b7d

Browse files
remove stroked style; add arc shape in the circular progress
1 parent 7128163 commit 5ca7b7d

File tree

6 files changed

+79
-229
lines changed

6 files changed

+79
-229
lines changed

Examples/DemosApp/DemosApp/ComponentsPreview/PreviewPages/CircularProgressPreview.swift

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ struct CircularProgressPreview: View {
77
@State private var currentValue: CGFloat = Self.initialValue
88

99
private let circularProgress = UKCircularProgress(
10+
initialValue: Self.initialValue,
1011
model: Self.initialModel
1112
)
1213

@@ -43,9 +44,9 @@ struct CircularProgressPreview: View {
4344
Text("8").tag(Optional<CGFloat>.some(8))
4445
}
4546
SizePicker(selection: self.$model.size)
46-
Picker("Style", selection: self.$model.style) {
47-
Text("Light").tag(CircularProgressVM.Style.light)
48-
Text("Striped").tag(CircularProgressVM.Style.striped)
47+
Picker("Shape", selection: self.$model.shape) {
48+
Text("Circle").tag(CircularProgressVM.Shape.circle)
49+
Text("Arc").tag(CircularProgressVM.Shape.arc)
4950
}
5051
}
5152
.onReceive(self.timer) { _ in
@@ -71,7 +72,7 @@ struct CircularProgressPreview: View {
7172

7273
private static var initialModel = CircularProgressVM {
7374
$0.label = "0%"
74-
$0.style = .light
75+
$0.shape = .arc
7576
}
7677
}
7778

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import Foundation
2+
3+
extension CircularProgressVM {
4+
/// Defines the shapes for the circular progress component.
5+
public enum Shape {
6+
case circle
7+
case arc
8+
}
9+
}

Sources/ComponentsKit/Components/CircularProgress/Models/CircularProgressStyle.swift

Lines changed: 0 additions & 9 deletions
This file was deleted.

Sources/ComponentsKit/Components/CircularProgress/Models/CircularProgressVM.swift

Lines changed: 36 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -7,34 +7,34 @@ public struct CircularProgressVM: ComponentVM {
77
/// Defaults to `.accent`.
88
public var color: ComponentColor = .accent
99

10-
/// The style of the circular progress indicator.
11-
///
12-
/// Defaults to `.light`.
13-
public var style: Style = .light
10+
/// The font used for the circular progress label text.
11+
public var font: UniversalFont?
1412

15-
/// The size of the circular progress.
16-
///
17-
/// Defaults to `.medium`.
18-
public var size: ComponentSize = .medium
13+
/// An optional label to display inside the circular progress.
14+
public var label: String?
1915

20-
/// The minimum value of the circular progress.
21-
///
22-
/// Defaults to `0`.
23-
public var minValue: CGFloat = 0
16+
/// The width of the circular progress stroke.
17+
public var lineWidth: CGFloat?
2418

2519
/// The maximum value of the circular progress.
2620
///
2721
/// Defaults to `100`.
2822
public var maxValue: CGFloat = 100
2923

30-
/// The width of the circular progress stroke.
31-
public var lineWidth: CGFloat?
24+
/// The minimum value of the circular progress.
25+
///
26+
/// Defaults to `0`.
27+
public var minValue: CGFloat = 0
3228

33-
/// An optional label to display inside the circular progress.
34-
public var label: String?
29+
/// The shape of the circular progress indicator.
30+
///
31+
/// Defaults to `.circle`.
32+
public var shape: Shape = .circle
3533

36-
/// The font used for the circular progress label text.
37-
public var font: UniversalFont?
34+
/// The size of the circular progress.
35+
///
36+
/// Defaults to `.medium`.
37+
public var size: ComponentSize = .medium
3838

3939
/// Initializes a new instance of `CircularProgressVM` with default values.
4040
public init() {}
@@ -68,6 +68,22 @@ extension CircularProgressVM {
6868
y: self.preferredSize.height / 2
6969
)
7070
}
71+
var startAngle: CGFloat {
72+
switch self.shape {
73+
case .circle:
74+
return -0.5 * .pi
75+
case .arc:
76+
return 0.75 * .pi
77+
}
78+
}
79+
var endAngle: CGFloat {
80+
switch self.shape {
81+
case .circle:
82+
return 1.5 * .pi
83+
case .arc:
84+
return 2.25 * .pi
85+
}
86+
}
7187
var titleFont: UniversalFont {
7288
if let font {
7389
return font
@@ -81,44 +97,6 @@ extension CircularProgressVM {
8197
return .lgCaption
8298
}
8399
}
84-
var stripeWidth: CGFloat {
85-
return 0.5
86-
}
87-
private func stripesCGPath(in rect: CGRect) -> CGMutablePath {
88-
let stripeSpacing: CGFloat = 3
89-
let stripeAngle: Angle = .degrees(135)
90-
91-
let path = CGMutablePath()
92-
let step = stripeWidth + stripeSpacing
93-
let radians = stripeAngle.radians
94-
95-
let dx: CGFloat = rect.height * tan(radians)
96-
for x in stride(from: 0, through: rect.width + rect.height, by: step) {
97-
let topLeft = CGPoint(x: x, y: 0)
98-
let bottomRight = CGPoint(x: x + dx, y: rect.height)
99-
100-
path.move(to: topLeft)
101-
path.addLine(to: bottomRight)
102-
path.closeSubpath()
103-
}
104-
return path
105-
}
106-
}
107-
108-
extension CircularProgressVM {
109-
func gap(for normalized: CGFloat) -> CGFloat {
110-
return normalized > 0 ? 0.05 : 0
111-
}
112-
113-
func stripedArcStart(for normalized: CGFloat) -> CGFloat {
114-
let gapValue = self.gap(for: normalized)
115-
return max(0, min(1, normalized + gapValue))
116-
}
117-
118-
func stripedArcEnd(for normalized: CGFloat) -> CGFloat {
119-
let gapValue = self.gap(for: normalized)
120-
return 1 - gapValue
121-
}
122100
}
123101

124102
extension CircularProgressVM {
@@ -133,33 +111,6 @@ extension CircularProgressVM {
133111
// MARK: - UIKit Helpers
134112

135113
extension CircularProgressVM {
136-
var isStripesLayerHidden: Bool {
137-
switch self.style {
138-
case .light:
139-
return true
140-
case .striped:
141-
return false
142-
}
143-
}
144-
var isBackgroundLayerHidden: Bool {
145-
switch self.style {
146-
case .light:
147-
return false
148-
case .striped:
149-
return true
150-
}
151-
}
152-
func stripesBezierPath(in rect: CGRect) -> UIBezierPath {
153-
let center = CGPoint(x: rect.midX, y: rect.midY)
154-
let path = UIBezierPath(cgPath: self.stripesCGPath(in: rect))
155-
var transform = CGAffineTransform.identity
156-
transform = transform
157-
.translatedBy(x: center.x, y: center.y)
158-
.rotated(by: -CGFloat.pi / 2)
159-
.translatedBy(x: -center.x, y: -center.y)
160-
path.apply(transform)
161-
return path
162-
}
163114
func shouldInvalidateIntrinsicContentSize(_ oldModel: Self) -> Bool {
164115
return self.preferredSize != oldModel.preferredSize
165116
}
@@ -170,12 +121,7 @@ extension CircularProgressVM {
170121
return self.minValue != oldModel.minValue
171122
|| self.maxValue != oldModel.maxValue
172123
}
173-
}
174-
175-
// MARK: - SwiftUI Helpers
176-
177-
extension CircularProgressVM {
178-
func stripesPath(in rect: CGRect) -> Path {
179-
Path(self.stripesCGPath(in: rect))
124+
func shouldUpdateShape(_ oldModel: Self) -> Bool {
125+
return self.shape != oldModel.shape
180126
}
181127
}

Sources/ComponentsKit/Components/CircularProgress/SUCircularProgress.swift

Lines changed: 17 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,22 @@ public struct SUCircularProgress: View {
3333
public var body: some View {
3434
ZStack {
3535
// Background part
36-
Group {
37-
switch self.model.style {
38-
case .light:
39-
self.lightBackground
40-
case .striped:
41-
self.stripedBackground
42-
}
36+
Path { path in
37+
path.addArc(
38+
center: self.model.center,
39+
radius: self.model.radius,
40+
startAngle: .radians(self.model.startAngle),
41+
endAngle: .radians(self.model.endAngle),
42+
clockwise: false
43+
)
4344
}
45+
.stroke(
46+
self.model.color.background.color,
47+
style: StrokeStyle(
48+
lineWidth: self.model.circularLineWidth,
49+
lineCap: .round
50+
)
51+
)
4452
.frame(
4553
width: self.model.preferredSize.width,
4654
height: self.model.preferredSize.height
@@ -51,8 +59,8 @@ public struct SUCircularProgress: View {
5159
path.addArc(
5260
center: self.model.center,
5361
radius: self.model.radius,
54-
startAngle: .radians(0),
55-
endAngle: .radians(2 * .pi),
62+
startAngle: .radians(self.model.startAngle),
63+
endAngle: .radians(self.model.endAngle),
5664
clockwise: false
5765
)
5866
}
@@ -64,7 +72,6 @@ public struct SUCircularProgress: View {
6472
lineCap: .round
6573
)
6674
)
67-
.rotationEffect(.degrees(-90))
6875
.frame(
6976
width: self.model.preferredSize.width,
7077
height: self.model.preferredSize.height
@@ -82,62 +89,4 @@ public struct SUCircularProgress: View {
8289
value: self.progress
8390
)
8491
}
85-
86-
// MARK: - Subviews
87-
88-
var lightBackground: some View {
89-
Path { path in
90-
path.addArc(
91-
center: self.model.center,
92-
radius: self.model.radius,
93-
startAngle: .radians(0),
94-
endAngle: .radians(2 * .pi),
95-
clockwise: false
96-
)
97-
}
98-
.stroke(
99-
self.model.color.background.color,
100-
lineWidth: self.model.circularLineWidth
101-
)
102-
}
103-
104-
var stripedBackground: some View {
105-
StripesShapeCircularProgress(model: self.model)
106-
.stroke(
107-
self.model.color.main.color,
108-
style: StrokeStyle(lineWidth: self.model.stripeWidth)
109-
)
110-
.mask {
111-
Path { maskPath in
112-
maskPath.addArc(
113-
center: self.model.center,
114-
radius: self.model.radius,
115-
startAngle: .radians(0),
116-
endAngle: .radians(2 * .pi),
117-
clockwise: false
118-
)
119-
}
120-
.trim(
121-
from: self.model.stripedArcStart(for: self.progress),
122-
to: self.model.stripedArcEnd(for: self.progress)
123-
)
124-
.stroke(
125-
style: StrokeStyle(
126-
lineWidth: self.model.circularLineWidth,
127-
lineCap: .round
128-
)
129-
)
130-
}
131-
.rotationEffect(.degrees(-90))
132-
}
133-
}
134-
135-
// MARK: - Helpers
136-
137-
struct StripesShapeCircularProgress: Shape, @unchecked Sendable {
138-
var model: CircularProgressVM
139-
140-
func path(in rect: CGRect) -> Path {
141-
self.model.stripesPath(in: rect)
142-
}
14392
}

0 commit comments

Comments
 (0)