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

SwiftUI 如何实现视图沿圆周运动动画的同时保持自身朝向固定

要实现视图沿圆周运动但自身朝向固定,有两种常用的实现方案:

方案1:反向旋转抵消(改动最小,适配现有代码)

核心逻辑:外层容器旋转多少度,就给内部需要保持正向的内容添加相同角度的反向旋转,抵消旋转效果即可。修改后的完整代码如下:

struct RotateObjectInEllipsePath: View {
    
  let timer = Timer.publish(every: 0.1, on: .main, in: .common).autoconnect()
  let circleWidth: CGFloat = 250.0
  
  @State private var angle: Double = .zero
    
  var body: some View {
    ZStack {
      Circle()
        .strokeBorder(Color.red, lineWidth: 2)
        .frame(width: circleWidth, height: circleWidth)
      
      // 外层做旋转,控制圆周运动轨迹
      Group {
        Circle()
          .foregroundColor(.purple)
          .frame(width: 50, height: 50)
          .offset(x: circleWidth/2)
          .overlay(
            Text("Hi")
              .offset(x: circleWidth/2)
          )
      }
      // 内层反向旋转,抵消外层的旋转效果,保持内容正向
      .rotationEffect(.degrees(-angle))
      .onReceive(timer) { _ in
        angle += 1
      }
      .animation(.default)
      .rotationEffect(.degrees(angle))
    }
  }
}

struct RotateObjectInEllipsePath_Previews: PreviewProvider {
    static var previews: some View {
        RotateObjectInEllipsePath()
    }
}

方案2:直接计算坐标偏移(无旋转逻辑,更直观)

不需要依赖旋转实现圆周运动,直接通过三角函数计算每一刻的x、y偏移量,内容自然不会发生旋转:

struct RotateObjectInEllipsePath: View {
    
  let timer = Timer.publish(every: 0.1, on: .main, in: .common).autoconnect()
  let circleWidth: CGFloat = 250.0
  // 圆周运动半径
  private var radius: CGFloat { circleWidth / 2 }
  
  @State private var angle: Double = .zero
    
  var body: some View {
    ZStack {
      Circle()
        .strokeBorder(Color.red, lineWidth: 2)
        .frame(width: circleWidth, height: circleWidth)
      
      VStack(spacing: 0) {
        Circle()
          .foregroundColor(.purple)
          .frame(width: 50, height: 50)
        Text("Hi")
      }
      // 直接用三角函数计算偏移位置
      .offset(
        x: radius * cos(angle * .pi / 180),
        y: radius * sin(angle * .pi / 180)
      )
      .onReceive(timer) { _ in
        angle += 1
      }
      .animation(.default)
    }
  }
}

struct RotateObjectInEllipsePath_Previews: PreviewProvider {
    static var previews: some View {
        RotateObjectInEllipsePath()
    }
}

两种方案都可以实现目标效果,方案1改动量最小,方案2逻辑更清晰,没有旋转叠加的计算成本,可以根据自己的需求选择。

内容的提问来源于stack exchange,提问作者maiko-m

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 01:24:04