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

如何在SwiftUI中实现单次脉冲动画效果?

SwiftUI 实现视图缩放后自动恢复的简洁方案

我想给视图添加缩放动画,动画完成后自动恢复到原始尺寸。目前我用DispatchQueue.main.asyncAfter配合动画时长来实现,代码如下,请问有没有更符合SwiftUI风格或者更简洁的实现方式?

import SwiftUI

struct ExampleView: View {
    @State private var isPulse = false

    var body: some View {
        VStack {
            Text("Hello")
                .scaleEffect(isPulse ? 3 : 1)
            ZStack {
                Capsule()
                    .frame(width: 100, height: 40)
                    .foregroundColor(.pink)
                Text("Press me")
            }
            .onTapGesture {
                let animationDuration = 0.4
                withAnimation(.easeInOut(duration: animationDuration)) {
                    isPulse.toggle()
                }
                DispatchQueue.main.asyncAfter(deadline: .now() + animationDuration) {
                    withAnimation(.easeInOut) {
                        isPulse.toggle()
                    }
                }
            }
        }
    }
}

struct ExampleView_Previews: PreviewProvider {
    static var previews: some View {
        ExampleView()
    }
}

更符合SwiftUI风格的实现方式

利用SwiftUI动画原生的autoreverses(自动反转)和repeatCount(重复次数)属性,可以彻底摆脱手动延迟反转状态的写法,代码更简洁且符合框架设计思想:

import SwiftUI

struct ExampleView: View {
    @State private var isPulse = false

    var body: some View {
        VStack {
            Text("Hello")
                .scaleEffect(isPulse ? 3 : 1)
            
            ZStack {
                Capsule()
                    .frame(width: 100, height: 40)
                    .foregroundColor(.pink)
                Text("Press me")
            }
            .onTapGesture {
                // 先将状态设为放大
                isPulse = true
                // 触发自动反转的动画:先缩放到原始尺寸,动画结束后自动回到初始状态
                withAnimation(.easeInOut(duration: 0.4).repeatCount(1, autoreverses: true)) {
                    isPulse = false
                }
            }
        }
    }
}

struct ExampleView_Previews: PreviewProvider {
    static var previews: some View {
        ExampleView()
    }
}

方案优势

  • 无需手动管理动画时长与延迟时间的同步,修改动画时长时只需调整一处
  • 完全利用SwiftUI的动画系统,避免了手动调度队列的额外代码
  • 逻辑更直观:通过动画的自动反转特性,自然实现"缩放→恢复"的完整流程

另一种可选方案:链式动画

如果需要更精细的控制(比如放大和恢复的动画曲线不同),可以用链式的withAnimation配合delay:

.onTapGesture {
    withAnimation(.easeIn(duration: 0.2)) {
        isPulse = true
    }
    withAnimation(.easeOut(duration: 0.2).delay(0.2)) {
        isPulse = false
    }
}

这种方式可以分别定义放大和恢复阶段的动画参数,同样不需要依赖DispatchQueue。


内容的提问来源于stack exchange,提问作者Martina K Drlík

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 04:25:39