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

SwiftUI图片缩放透明度循环动画:切换至录制状态重复触发

解决SwiftUI录制按钮动画重复触发问题

核心问题是.onAppear仅在视图首次渲染时执行,当从其他状态切回recording时,对应的ZStack视图可能并未被销毁重建,所以动画不会重新触发。我们可以通过监听状态变化来替代.onAppear,确保每次进入recording状态都能启动动画。

修改方案

  1. 监听recordState的变化,当状态切换为.recording时启动循环动画
  2. 切换到其他状态时,重置动画参数并停止循环

修改后的完整代码

enum RecordState {
    case recording
    case notRecording
    case none
}

// 假设这是你的View结构体内部代码
@State private var recordState: RecordState = .none
@State private var scale: CGFloat = 0.8 // 动画初始缩放值
@State private var opacity: Double = 1.0 // 动画初始透明度

VStack {
    Button {
        switch recordState {
        case .recording:
            recordState = .notRecording
        case .notRecording:
            recordState = .none
        case .none:
            recordState = .recording
        }
    } label: {
        switch recordState {
        case .recording:
            ZStack {
                Image("ic_record_cancel")
                    .resizable()
                    .frame(width: 76, height: 76)
                    .zIndex(1.0)
                
                Image("ic_record_effect")
                    .resizable()
                    .frame(width: 76, height: 76)
                    .zIndex(0.1)
                    .opacity(opacity)
                    .scaleEffect(scale)
                    // 监听recordState变化,替代onAppear
                    .onChange(of: recordState) { newState in
                        if newState == .recording {
                            // 创建循环动画
                            let baseAnimation = Animation.linear(duration: 0.8).delay(0.2)
                            let repeatedAnimation = baseAnimation.repeatForever(autoreverses: true)
                            withAnimation(repeatedAnimation) {
                                scale = 1.0
                                opacity = 0.6
                            }
                        } else {
                            // 切换到其他状态时重置动画参数,停止动画
                            withAnimation(.linear) {
                                scale = 0.8
                                opacity = 1.0
                            }
                        }
                    }
            }
        case .notRecording, .none:
            Image("ic_record_start")
                .resizable()
                .frame(width: 76, height: 76)
        }
    }
}

关键说明

  • 把动画触发逻辑从.onAppear移到.onChange(of: recordState)中,每次状态变为.recording都会执行动画启动代码
  • 切换到非录制状态时,重置scale和opacity到初始值,自动停止循环动画
  • 初始的scale和opacity设为动画的起始状态,保证动画过渡自然

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 22:17:21