You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI中如何获取沿圆周持续移动视图的实时位置?

解决方法

你的小圆圈位置是由angle状态和三角函数关系决定的,不需要直接从视图读取位置,而是可以通过实时计算得到当前位置,具体实现如下:

1. 添加位置计算属性

在ContentView中新增计算属性,根据实时变化的angle和已知半径,推导小圆圈的坐标:

struct ContentView: View {
    
    let mainCircleDiameter: CGFloat = 280
    let outerCircleDiameter: CGFloat = 320
    
    @State private var angle: Angle = .degrees(0)
    
    // 实时计算小圆圈相对于父视图中心的位置
    private var currentPosition: CGPoint {
        let radius = outerCircleDiameter / 2
        let radians = angle.radians
        // 适配SwiftUI坐标系统(y轴向下),调整三角函数符号
        let x = radius * cos(radians)
        let y = radius * sin(radians)
        return CGPoint(x: x, y: y)
    }
    
    var body: some View {
        ZStack {
            Color.orange.ignoresSafeArea(.all, edges: .all)
            GeometryReader { geo in
                ZStack {
                    Circle()
                        .stroke(lineWidth: 10)
                        .frame(width: mainCircleDiameter)
                    
                    Circle()
                        .frame(width: 25)
                        .offset(y: outerCircleDiameter / 2)
                        .rotationEffect(angle)
                        .onAppear {
                            withAnimation(
                                .linear(duration: 6)
                                .repeatForever(autoreverses: false)) {
                                    angle.degrees = 360
                            }
                        }
                }
                .frame(width: geo.size.width, height: geo.size.height)
                // 示例:实时打印位置
                .onChange(of: angle) { _ in
                    print("当前位置:\(currentPosition)")
                }
            }
            .frame(width: 400, height: 400)
            // 示例:在界面显示位置
            .overlay(
                Text("位置:(\(String(format: "%.1f", currentPosition.x)), \(String(format: "%.1f", currentPosition.y)))")
                    .foregroundColor(.white)
                    .font(.headline)
                    .padding()
            )
        }
    }
}

2. 扩展说明

  • 如果需要获取小圆圈相对于屏幕的绝对位置,可以结合GeometryReader的代理信息,将相对位置转换为屏幕坐标:

    private func absoluteScreenPosition(in geo: GeometryProxy) -> CGPoint {
        let parentCenter = CGPoint(x: geo.size.width/2, y: geo.size.height/2)
        let screenOrigin = geo.frame(in: .global).origin
        return CGPoint(
            x: screenOrigin.x + parentCenter.x + currentPosition.x,
            y: screenOrigin.y + parentCenter.y + currentPosition.y
        )
    }
    

    在GeometryReader内部调用该方法即可拿到屏幕绝对坐标。

  • 为什么不直接读取视图frame?
    SwiftUI是声明式框架,视图位置由状态推导而来,直接读取frame会破坏状态驱动逻辑,且动画过程中无法获取到实时的中间值,通过状态计算是最可靠的方式。

内容的提问来源于stack exchange,提问作者Dev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 00:42:50