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
相关产品推荐
相关产品推荐

