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

SwiftUI中如何判断PhaseAnimator动画何时完成

SwiftUI中判断PhaseAnimator完成周期动画并实现通知的方法

核心逻辑

PhaseAnimator的动画周期由预定义的阶段序列驱动,判断整个周期完成的核心是跟踪阶段(Phase)的状态变化:当动画从最后一个阶段切换回初始阶段(完成一轮循环),或者单次动画执行到最后一个阶段时,即可判定周期完成,此时触发通知即可。

实现步骤与代码示例

1. 定义动画阶段枚举

先明确所有动画阶段,方便管理序列顺序:

enum AnimationPhase: CaseIterable {
    case start, middle, end // 可根据动画需求自定义阶段数量与类型
}

2. 跟踪阶段变化并触发完成通知

通过@State变量记录当前和历史阶段,在阶段切换时检测周期完成条件:

struct CycleAnimationView: View {
    @State private var currentPhase: AnimationPhase = .start
    @State private var previousPhase: AnimationPhase = .start
    
    // 自定义通知名称,避免系统通知冲突
    private let cycleCompletedNotification = NSNotification.Name("AnimationCycleFinished")
    
    var body: some View {
        // 示例动画视图:随阶段缩放变色的圆形
        Circle()
            .frame(width: 100, height: 100)
            .phaseAnimator(AnimationPhase.allCases, trigger: currentPhase) { content, phase in
                content
                    .foregroundColor(phase == .start ? .blue : phase == .middle ? .green : .red)
                    .scaleEffect(phase == .start ? 1 : phase == .middle ? 1.5 : 1)
            } animation: { phase in
                // 为每个阶段配置独立动画参数
                switch phase {
                case .start: .easeIn(duration: 0.5)
                case .middle: .easeOut(duration: 0.5)
                case .end: .easeInOut(duration: 0.5)
                }
            }
            .onChange(of: currentPhase) { oldPhase, newPhase in
                previousPhase = oldPhase
                
                // 循环动画完成判定:从最后一个阶段切回初始阶段
                if newPhase == .start && oldPhase == .end {
                    sendCompletionNotification()
                }
                
                // 单次动画完成判定:当前阶段为最后一个阶段
                // if newPhase == .end {
                //     sendCompletionNotification()
                // }
            }
            // 可选:添加手动触发动画的按钮
            .overlay(
                Button("启动循环") {
                    withAnimation {
                        // 手动切换阶段,模拟循环逻辑
                        currentPhase = currentPhase == .end ? .start : 
                        AnimationPhase.allCases[AnimationPhase.allCases.firstIndex(of: currentPhase)! + 1]
                    }
                }
                .padding()
                .background(.black)
                .foregroundColor(.white)
                .cornerRadius(8)
                , alignment: .bottom
            )
    }
    
    private func sendCompletionNotification() {
        // 发送全局通知
        NotificationCenter.default.post(name: cycleCompletedNotification, object: nil)
        print("动画周期已完成")
    }
}

3. 监听动画完成通知

在需要响应动画完成的视图中,通过onReceive监听通知并执行后续逻辑:

struct ContentView: View {
    private let cycleCompletedNotification = NSNotification.Name("AnimationCycleFinished")
    @State private var animationStatus: String = "等待动画启动"
    
    var body: some View {
        VStack(spacing: 30) {
            CycleAnimationView()
            
            Text("当前状态:\(animationStatus)")
                .font(.headline)
        }
        .onReceive(NotificationCenter.default.publisher(for: cycleCompletedNotification)) { _ in
            animationStatus = "动画周期完成!"
            // 这里可以添加弹窗、数据更新等业务逻辑
        }
    }
}

额外说明

  • 如果使用PhaseAnimator的自动循环(通过repeatBehavior配置),上述阶段变化的判断逻辑依然有效,每次循环结束都会触发通知。
  • 若不需要全局通知,也可以直接在sendCompletionNotification方法中直接调用业务逻辑闭包,替代NotificationCenter。

内容的提问来源于stack exchange,提问作者Dubon Ya'ar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 19:50:12