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

如何在SwiftUI中实现类似UIKit的帧动画(仿魂斗罗像素风波动)

SwiftUI 实现魂斗罗风格重复波动动画序列

核心解决方案:封装可复用的动画修饰符

针对你的需求,我们可以通过**自定义ViewModifier**封装完整的动画序列逻辑,既避免在onAppear中硬编码定时器,又能让任意视图快速应用该动画,完全符合SwiftUI的声明式设计理念。

完整实现代码

1. 自定义动画修饰符

import SwiftUI

struct ContraWaveAnimation: ViewModifier {
    @State private var offsetY: CGFloat = 0
    // 可调整的动画参数
    private let singleMoveDistance: CGFloat = 10
    private let animationSpeed: Double = 0.2
    private let pauseDuration: Double = 0.3
    
    func body(content: Content) -> some View {
        content
            .offset(y: offsetY)
            .task {
                // 无限循环执行动画序列
                while true {
                    // 步骤1:上移
                    withAnimation(.linear(duration: animationSpeed)) {
                        offsetY -= singleMoveDistance
                    }
                    // 步骤2:暂停
                    try? await Task.sleep(nanoseconds: UInt64(pauseDuration * 1e9))
                    
                    // 步骤3:上移
                    withAnimation(.linear(duration: animationSpeed)) {
                        offsetY -= singleMoveDistance
                    }
                    // 步骤4:暂停
                    try? await Task.sleep(nanoseconds: UInt64(pauseDuration * 1e9))
                    
                    // 步骤5:下移
                    withAnimation(.linear(duration: animationSpeed)) {
                        offsetY += singleMoveDistance
                    }
                    // 步骤6:暂停
                    try? await Task.sleep(nanoseconds: UInt64(pauseDuration * 1e9))
                    
                    // 步骤7:下移
                    withAnimation(.linear(duration: animationSpeed)) {
                        offsetY += singleMoveDistance
                    }
                    // 步骤8:暂停
                    try? await Task.sleep(nanoseconds: UInt64(pauseDuration * 1e9))
                }
            }
    }
}

2. 扩展View简化调用

extension View {
    func contraWaveAnimation() -> some View {
        self.modifier(ContraWaveAnimation())
    }
}

3. 任意视图快速应用动画

struct ContentView: View {
    var body: some View {
        VStack(spacing: 50) {
            // 给文本应用动画
            Text("❤️")
                .font(.system(size: 200, weight: .bold))
                .contraWaveAnimation()
            
            // 给自定义视图应用动画
            CustomRocketView()
                .contraWaveAnimation()
        }
    }
}

// 自定义视图示例
struct CustomRocketView: View {
    var body: some View {
        Image(systemName: "rocket")
            .font(.system(size: 100))
            .foregroundColor(.orange)
    }
}

方案优势说明

  1. 脱离onAppear硬编码:使用SwiftUI的.task修饰符管理异步动画序列,视图出现时自动启动,消失时自动终止,完全贴合视图生命周期,避免内存泄漏。
  2. 任意视图复用:通过ViewModifier封装动画逻辑,任何视图只需调用.contraWaveAnimation()即可应用效果,无需直接操作视图实例。
  3. 参数灵活调整:可以通过修改singleMoveDistance、animationSpeed、pauseDuration参数,快速调整动画的幅度、速度和停顿间隔。
  4. 像素风优化(可选):如果需要更贴近魂斗罗的像素波动效果,可以在动画步骤中加入微小的X轴偏移,比如:
    @State private var offsetX: CGFloat = 0
    // 在上移动画中添加:
    offsetX += 2
    // 在下移动画中添加:
    offsetX -= 2
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 22:57:35