首页 > 解决方案 > SwiftUI 圆位置 x 和 y

问题描述

我很难找出正确的方法来找到要放置的 x 和 y 坐标,以及我正在制作的进度视图的正确位置Imageoverlay我希望最终结果看起来像屏幕截图,只是不确定我会使用什么公式。我的数学技能至少可以说是低于标准的。

GeometryReader { geometry in
    ZStack {
        Circle()
            .trim(from: 0.0, to: 0.5)
            .stroke(Color.blue, style: StrokeStyle(lineWidth: 5))
            .rotationEffect(.degrees(-180))
            .frame(width: geometry.size.width)
            .opacity(0.5)
            .overlay(Circle()
                        .trim(from: 0.0, to: CGFloat(configuration.fractionCompleted ?? 0) / 2)
                        .stroke(Color.blue, style: StrokeStyle(lineWidth: 5))
                        .rotationEffect(.degrees(-180))
                        .frame(width: geometry.size.width).overlay(
                            Circle()
                                .frame(width: 20, height: 20)
                                .position(x: 0, y: 0)
    }
}

在此处输入图像描述

标签: iosswiftswiftui

解决方案


您只需要非常基本的几何图形 在此处输入图像描述 您需要获取C点坐标。跟着这张图,就可以了(x, height / 2 - y)

要让y你知道sin α = CD/CA,就像ACD直角三角形一样。从哪里y = r * sin α

因为x我们看一下同一个三角形,但取 cos: cos α = AD/CA, cos α = (r-x)/r=>x = r - r * cos α = r * (1 - cos α)

你需要的最后一件事是α它很简单:半圆的最后一点 if Pi,所以你只需要将它与进度相乘。

struct ContentView: View {
    @State
    var progress: CGFloat = 0
    
    var body: some View {
        GeometryReader { geometry in
            let diameter = geometry.size.width
            let radius = diameter / 2
            let angle = progress * .pi
            ZStack {
                Circle()
                    .trim(from: 0.0, to: 0.5)
                    .stroke(Color.blue, style: StrokeStyle(lineWidth: 5))
                    .rotationEffect(.degrees(-180))
                    .frame(width: diameter)
                    .opacity(0.5)
                    .overlay(
                        Circle()
                            .trim(from: 0.0, to: progress / 2)
                            .stroke(Color.blue, style: StrokeStyle(lineWidth: 5))
                            .rotationEffect(.degrees(-180))
                            .frame(width: diameter)
                            .overlay(
                                Circle()
                                    .frame(width: 20, height: 20)
                                    .position(
                                        x: radius * (1 - cos(angle)),
                                        y: geometry.size.height / 2 - radius * sin(angle)
                                    )
                            )
                    )
            }
        }.onAppear {
            Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { timer in
                withAnimation {
                    progress += 0.04
                }
                if progress >= 1 {
                    timer.invalidate()
                }
            }
        }
    }
}

在此处输入图像描述


推荐阅读