import SwiftUI struct CustomLightSequenceAnimation: View { // 核心循环序列:按"123321123321"规律定义基础单元 private let baseSequence: [Int] = [1, 2, 3, 3, 2, 1, 1, 2, 3, 3, 2, 1] @State private var currentLight: Int = 1 // 当前显示的图片序号 @State private var sequenceIndex: Int = 0 // 当前在序列中的索引 // 淡入淡出透明度控制(确保切换丝滑) @State private var currentOpacity: CGFloat = 1.0 @State private var nextOpacity: CGFloat = 0.0 // 尺寸参数(适配正方形卡片) private let screenWidth = UIScreen.main.bounds.width private let squareSize: CGFloat private let imageSize: CGFloat init() { self.squareSize = screenWidth * 1.8 // 正方形背景尺寸 self.imageSize = squareSize / 3 // 光束卡片尺寸(1/3背景大小) } // 卡片中心位置(固定,确保摆正居中) private var centerPosition: CGPoint { CGPoint(x: screenWidth / 2, y: squareSize * 0.325) } var body: some View { ZStack { // 底部背景(正方形) SVGImage(svgName: "BlindBg") .frame(width: squareSize, height: squareSize) .position(centerPosition) // 当前显示的光束卡片(摆正状态) SVGImage(svgName: "Light\(currentLight)") .frame(width: imageSize, height: imageSize) .position(centerPosition) .opacity(currentOpacity) // 下一张待显示的光束卡片(提前加载,摆正状态) SVGImage(svgName: "Light\(nextLight)") .frame(width: imageSize, height: imageSize) .position(centerPosition) .opacity(nextOpacity) } .onAppear { startLoopAnimation() } } // 计算下一张卡片序号(基于当前索引循环) private var nextLight: Int { let nextIdx = (sequenceIndex + 1) % baseSequence.count return baseSequence[nextIdx] } // 启动循环切换动画 private func startLoopAnimation() { // 每1.2秒切换一次(可调整速度) Timer.scheduledTimer(withTimeInterval: 1.2, repeats: true) { _ in // 0.5秒淡入淡出过渡(丝滑无卡顿) withAnimation(Animation.easeInOut(duration: 0.5)) { currentOpacity = 0.0 nextOpacity = 1.0 } // 动画完成后更新状态(确保顺序无偏差) DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { currentLight = nextLight sequenceIndex = (sequenceIndex + 1) % baseSequence.count currentOpacity = 1.0 nextOpacity = 0.0 } } } } // 预览 struct CustomLightSequenceAnimation_Previews: PreviewProvider { static var previews: some View { CustomLightSequenceAnimation() } }