SwiftUI:如何以时钟样式修剪圆圈

gre*_*en8 2 geometry ios swift swiftui

我正在制作测验应用程序,需要创建类似于此图片的计时器

1

所以它不会以正常方式修剪,但我必须像时钟指针一样工作。我尝试使用自定义形状自己实际绘制它,因为我知道中心点、半径和起点。所以我花了几个小时,然后我放弃了,也许你可以告诉我是否有更简单的方法,或者你知道为什么我的代码不能按预期工作。

这是我的自定义形状:


struct ClockShape: Shape {
    var trim: Double
    
    func properPoint(_ rect: CGRect) -> CGPoint {
        let r: CGFloat = 2 //rect.height/2
        let s: CGFloat = 2 //rect.midX
        let tempLength: CGFloat = sqrt(abs(2*pow(r, 2) - (4 * r * cos(360 * trim))))
        let length = sqrt(abs(tempLength))
        let a: CGFloat = ((pow(r, 2) - sqrt(abs(length))) / (-2 * s)) - s
        let b: CGFloat = sqrt(abs(sqrt(abs(length)) - pow((a - s), 2)))
        
        return CGPoint(x: a, y: b)
    }
    
    func path(in rect: CGRect) -> Path {
        var path = Path()
        let point = properPoint(rect)
        
        path.move(to: CGPoint(x: rect.midX, y: rect.minY))
        path.addLine(to: CGPoint(x: rect.midX, y: rect.midY))
        path.addLine(to: CGPoint(x: point.x, y: point.y))
        path.addLine(to: CGPoint(x: rect.midX, y: rect.minY))
        
        return path
    }
}
Run Code Online (Sandbox Code Playgroud)

这是一个内容视图:

struct ContentView: View {
    var body: some View {
        VStack {
            ClockShape(trim: 0.5)
                .fill(Color.accentColor)
                .frame(width: 100, height: 100)
            
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

它应该绘制一个被“trim”值修剪的圆(例如 0.5 -> 50%)

Ash*_*lls 5

你把问题过于复杂化了。要绘制修剪后的圆,请使用Circle().trim。下面是一个缩放以适合其框架的示例,并带有动画。

struct ContentView: View {
    
    @State private var value: Double = 0
    
    var body: some View {
        VStack {
            clock(value)
                .frame(width: 120, height: 120)
            
            Slider(value: $value, in: 0...10)
        }
        .padding()
    }
    
    
    func clock(_ value: Double) -> some View {
        GeometryReader { proxy in
            ZStack {
                Circle()
                    .fill(.pink.opacity(0.3))
                Circle()
                    .inset(by: proxy.size.width / 4)
                    .trim(from: 0, to: value /  10)
                    .stroke(.pink.opacity(0.6), style: StrokeStyle(lineWidth: proxy.size.width / 2))
                    .rotationEffect(.radians(-.pi/2))
                    .animation(.linear, value: value)
                Text("\(Int(value))")
                    .font(Font.system(size: proxy.size.width / 2))
                    .bold()
                    .foregroundColor(.white)
            }
        }
    }
}

Run Code Online (Sandbox Code Playgroud)

在此输入图像描述