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

SwiftUI动画:如何让重复动画的时长逐次递减?

解决方案:手动链式触发递减时长的动画

直接使用withAnimation配合repeatCount无法实现每次重复时长递减的需求,因为重复动画会复用同一个动画配置,所有重复周期的时长都是相同的。要实现每次时长递减,需要手动逐个触发动画,利用动画的完成回调来衔接下一次周期。

以下是具体实现代码:

struct YourView: View {
    let imagename: String
    @State private var scale: CGFloat = 1.0
    // 剩余需要执行的缩放周期数
    @State private var remainingCycles = 5
    // 当前动画的单向时长(对应你原来的0.5秒缩放时长)
    @State private var currentSingleDuration = 0.5
    
    var body: some View {
        ImageView(named: imagename)
            .padding(.trailing, 16)
            .padding(.top, 105)
            .scaleEffect(scale)
            .onAppear {
                startScalingCycle()
            }
    }
    
    private func startScalingCycle() {
        // 剩余周期为0时停止动画
        guard remainingCycles > 0 else { return }
        
        // 配置当前周期的动画:单向时长currentSingleDuration,自动反向回到初始状态
        let animation = Animation.easeInOut(duration: currentSingleDuration)
            .autoreverses(true)
        
        withAnimation(animation) {
            scale = 0.5
        } completion: {
            // 动画完成(包括反向还原)后,更新参数并触发下一次
            remainingCycles -= 1
            // 时长递减0.1秒,同时避免时长过小导致异常
            currentSingleDuration = max(currentSingleDuration - 0.1, 0.1)
            // 递归触发下一个周期
            startScalingCycle()
        }
    }
}

代码说明:

  • 使用remainingCycles跟踪还需执行的完整缩放-还原周期数,初始值设为你需要的5次
  • currentSingleDuration记录当前动画的单向时长,每次完成后递减0.1秒,并用max限制最小时长(避免出现0或负数时长)
  • 每个周期通过autoreverses(true)自动实现从缩放状态还原到初始状态,和你原代码的动画行为一致
  • 动画完成的completion回调是关键,在这里更新参数并递归触发下一次动画,实现链式的时长递减效果

可选调整:

如果你想要的是整个缩放-还原周期的总时长递减0.1秒(比如第一次总时长0.5秒,第二次0.4秒),可以修改代码中的时长计算逻辑:

@State private var totalCycleDuration = 0.5 // 总周期时长

private func startScalingCycle() {
    guard remainingCycles > 0 else { return }
    
    let singleDuration = totalCycleDuration / 2
    let animation = Animation.easeInOut(duration: singleDuration)
        .autoreverses(true)
    
    withAnimation(animation) {
        scale = 0.5
    } completion: {
        remainingCycles -= 1
        totalCycleDuration = max(totalCycleDuration - 0.1, 0.1)
        startScalingCycle()
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 00:20:22