DFWatchStepCountCircle.swift 3.32 KB
//
//  DFWatchStepCountCircle.swift
//  iwatch
//
//  Created by 权海 on 2026/6/12.
//

import SwiftUI

struct DFWatchStepCountCircle: View {
    /// 0...1
    var progress: CGFloat

    /// 中间显示的分数
    var value: Int

    var lineWidth: CGFloat = 6
    var markerSize: CGFloat = 8

    private let gradientColors: [Color] = [
        Color(hex: "#845EEE"),
        Color(hex: "#845EEE"),
    ]

    var body: some View {
        GeometryReader { geometry in
            let size = min(geometry.size.width, geometry.size.height)
            let arcSize = size - markerSize
            let startAngle: CGFloat = 90
            let sweepAngle: CGFloat = 270
            let rotation = 0.128 * 360

            let clampedProgress = min(max(progress, 0), 1)

            ZStack {
                Color.black
                // 渐变进度圆弧
                Circle()
                    .trim(from: 0.25, to: 1)
                    .stroke(
                        AngularGradient(
                            gradient: Gradient(colors: gradientColors),
                            center: .center,
                            startAngle: .degrees(Double(startAngle)),
                            endAngle: .degrees(Double(startAngle + sweepAngle))
                        ),
                        style: StrokeStyle(
                            lineWidth: lineWidth,
                            lineCap: .round,
                            lineJoin: .round
                        )
                    )
                    .frame(width: arcSize, height: arcSize)
                    .rotationEffect(.degrees(rotation))
                    .opacity(0.3)
                Circle()
                    .trim(from: 0.25, to: 0.25 + progress * 3/4)
                    .stroke(
                        AngularGradient(
                            gradient: Gradient(colors: gradientColors),
                            center: .center,
                            startAngle: .degrees(Double(startAngle)),
                            endAngle: .degrees(Double(startAngle + sweepAngle))
                        ),
                        style: StrokeStyle(
                            lineWidth: lineWidth,
                            lineCap: .round,
                            lineJoin: .round
                        )
                    )
                    .frame(width: arcSize, height: arcSize)
                    .rotationEffect(.degrees(rotation))

                // 中间数值
                Text("\(value)")
                    .font(.system(size: 9, weight: .bold, design: .rounded))
                    .lineLimit(1)
                    .foregroundStyle(.white)
                    .frame(maxWidth: geometry.size.width - 20)
                    .minimumScaleFactor(0.8)
                    .offset(y: -size * 0.02)

                // 底部爱心
                FootprintsIcon(color: gradientColors.first!)
                    .frame(width: 14, height: 14)
                    .offset(y: geometry.size.height - 28)
            }
            .frame(width: size, height: size)
        }
        .aspectRatio(1, contentMode: .fit)
    }
}

struct FootprintsIcon: View {
    var color: Color

    var body: some View {
        Image(systemName: "shoeprints.fill")
            .resizable()
            .scaledToFit()
            .foregroundStyle(color)
    }
}