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

