struct RingShap: Shape {
var pointSize: CGFloat = 10.0
func path(in rect: CGRect) -> Path {
let drawRect = CGRectInset(rect, 0.5 * pointSize, 0.5 * pointSize)
var path = Path()
path.addArc(center: CGPoint(x: CGRectGetMidX(drawRect), y: CGRectGetMidY(drawRect)), radius: 0.5 * min(drawRect.size.width, drawRect.size.height), startAngle: Angle(degrees: 135), endAngle: Angle(degrees: 45), clockwise: false)
return path
}
}
struct RingClipShap: Shape {
var blankCenter: CGPoint = CGPointZero
var pointSize: CGFloat = 14.0
func path(in rect: CGRect) -> Path {
let r = 0.5 * pointSize;
let drawRect = CGRectInset(rect, -r, -r)
var blankPath = Path()
blankPath.addArc(center: blankCenter, radius: r, startAngle: Angle(degrees: 0), endAngle: Angle(degrees: 360), clockwise: true)
var showPath = Path(roundedRect: drawRect, cornerSize: CGSizeZero)
showPath.addPath(blankPath)
return showPath
}
}
public struct WeatherProgress: View {
var strokeColor: Color = .red
var pointColor: Color = .blue
var progress: CGFloat = 0.5
var pointSize: CGFloat = 10.0
var extendPointSize: CGFloat = 4.0
public var body: some View {
GeometryReader { geometry in
RingShap(pointSize: pointSize)
.stroke(.red, style: StrokeStyle(lineWidth: pointSize, lineCap: .round))
.frame(width: geometry.size.width, height: geometry.size.height)
.clipShape(RingClipShap(blankCenter: progressPointCenter(geometry.size), pointSize: pointSize + extendPointSize))
Path { path in
let centerPoint = progressPointCenter(geometry.size)
path.move(to: centerPoint)
path.addArc(center: centerPoint, radius: 0.5 * pointSize, startAngle: Angle(degrees: 0), endAngle: Angle(degrees: 360), clockwise: true)
}
.fill(pointColor)
}
.background(Color.clear)
}
func progressPointCenter(_ size: CGSize) -> CGPoint {
let rect = CGRectMake(0.5 * pointSize, 0.5 * pointSize, size.width - pointSize, size.height - pointSize)
let centerX = CGRectGetMidX(rect)
let centerY = CGRectGetMidY(rect)
let radius = 0.5 * min(rect.size.width, rect.size.height)
let startAngle = Double.pi * (135.0 / 180.0)
let endAngle = Double.pi * (45.0 / 180.0)
let totalAngle = Double.pi * 2.0 - startAngle + endAngle
var location = progress * totalAngle + startAngle
if location > (Double.pi * 2.0) {
location = location - Double.pi * 2.0
}
let lcx = centerX + radius * cos(location)
let lcy = centerY + radius * sin(location)
return CGPoint(x: lcx, y: lcy)
}
}