SwiftUI切换状态时如何实现流畅连续的动画?
解决SwiftUI滑块切换时矩形旋转卡顿的问题
你的问题核心是使用.id(level)导致视图被重置,旋转状态丢失从而产生卡顿。以下是两种可行的平滑过渡方案:
方案一:基于SwiftUI动画系统无缝衔接
移除.id(level),通过动态调整动画时长并衔接当前旋转状态实现平滑切换:
struct ContentView: View { @State private var level: Double = 0 @State private var rotation: Double = 0 var body: some View { VStack(spacing: 16) { Rectangle().fill(.red) .frame(width: 100, height: 100) .rotationEffect(Angle(degrees: rotation)) .animation( level > 0 ? .linear(duration: 2 / level).repeatForever(autoreverses: false) : nil, value: rotation ) Spacer().frame(height: 12) Slider(value: $level, in: 0...3, step: 1) HStack { Text("0").fontWeight(.semibold) Spacer() Text("1").fontWeight(.semibold) Spacer() Text("2").fontWeight(.semibold) Spacer() Text("3").fontWeight(.semibold) } } .padding(16) .onChange(of: level) { _ in // 保留当前旋转的实际角度(取360的余数),避免数值无限累加 let currentAngle = rotation.truncatingRemainder(dividingBy: 360) rotation = currentAngle // 触发新的旋转动画 withAnimation { rotation += 360 } } } }
关键改动说明:
- 移除
.id(level),防止视图被销毁重建,保留当前旋转状态 - 计算当前旋转角度的余数,将rotation重置为该值,避免数值持续增大
- 用
withAnimation触发新动画,新动画基于新的level值计算时长,从当前角度无缝开始旋转
方案二:Timer手动驱动旋转(更灵活的速度控制)
通过Timer实时更新旋转角度,直接响应滑块值变化,完全避免动画重置问题:
struct ContentView: View { @State private var level: Double = 0 @State private var rotation: Double = 0 // 每0.01秒触发一次更新,保证旋转流畅 private let updateTimer = Timer.publish(every: 0.01, on: .main, in: .common).autoconnect() var body: some View { VStack(spacing: 16) { Rectangle().fill(.red) .frame(width: 100, height: 100) .rotationEffect(Angle(degrees: rotation)) Spacer().frame(height: 12) Slider(value: $level, in: 0...3, step: 1) HStack { Text("0").fontWeight(.semibold) Spacer() Text("1").fontWeight(.semibold) Spacer() Text("2").fontWeight(.semibold) Spacer() Text("3").fontWeight(.semibold) } } .padding(16) .onReceive(updateTimer) { _ in guard level > 0 else { return } // 按滑块值计算每秒旋转角度:对应原逻辑中2秒转360度的速度比例 rotation += level * 1.8 } } }
关键改动说明:
- 用Timer实时驱动rotation值更新,速度直接由level控制
- 无需动画修饰符,旋转状态持续累加,滑块切换时速度平滑过渡
- 避免了动画系统重置的问题,适合需要实时调整速度的场景
内容的提问来源于stack exchange,提问作者duckSern1108
相关产品推荐
相关产品推荐

