SwiftUI 环形进度条

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)
    }
}

 

posted @ 2023-03-15 13:33  雨筱逸悠  阅读(119)  评论(0编辑  收藏  举报