From ccdc46236d97f52804cb4b73232158ab0079cdc7 Mon Sep 17 00:00:00 2001 From: Junhui Chen Date: Thu, 11 Sep 2025 22:06:08 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E8=B0=83=E6=95=B4=E5=8A=A8=E7=94=BB?= =?UTF-8?q?=E5=A4=A7=E5=B0=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Components/BlindBoxAnimationView.swift | 3 ++ wake/SharedUI/Animation/LottieView.swift | 50 ++++++++++++++----- 2 files changed, 41 insertions(+), 12 deletions(-) diff --git a/wake/Features/BlindBox/Components/BlindBoxAnimationView.swift b/wake/Features/BlindBox/Components/BlindBoxAnimationView.swift index fddb069..5c65880 100644 --- a/wake/Features/BlindBox/Components/BlindBoxAnimationView.swift +++ b/wake/Features/BlindBox/Components/BlindBoxAnimationView.swift @@ -15,6 +15,7 @@ struct BlindBoxAnimationView: View { case .ready: ZStack { LottieView(name: "ready", isPlaying: true) + Color.clear .contentShape(Rectangle()) .onTapGesture { @@ -29,8 +30,10 @@ struct BlindBoxAnimationView: View { Image("Empty") .resizable() .scaledToFit() + .padding(40) } } .frame(width: 300, height: 300) + .animation(.easeInOut(duration: 0.5), value: phase) } } diff --git a/wake/SharedUI/Animation/LottieView.swift b/wake/SharedUI/Animation/LottieView.swift index f3b7a56..41f438c 100644 --- a/wake/SharedUI/Animation/LottieView.swift +++ b/wake/SharedUI/Animation/LottieView.swift @@ -14,45 +14,71 @@ struct LottieView: UIViewRepresentable { self.isPlaying = isPlaying } - func makeUIView(context: Context) -> LottieAnimationView { + func makeUIView(context: Context) -> UIView { + // 使用容器视图承载 LottieAnimationView,确保 SwiftUI 的 frame 约束能生效 + let container = UIView() + container.clipsToBounds = true + let animationView = LottieAnimationView() - + animationView.translatesAutoresizingMaskIntoConstraints = false + // 方法1: 直接使用文件名加载 if let animation = LottieAnimation.named(name) { animationView.animation = animation - } + } // 方法2: 如果方法1失败,尝试使用文件路径加载 else if let path = Bundle.main.path(forResource: name, ofType: "json") { let animation = LottieAnimation.filepath(path) animationView.animation = animation } - + // 配置动画 animationView.loopMode = loopMode animationView.animationSpeed = animationSpeed animationView.contentMode = .scaleAspectFit animationView.backgroundBehavior = .pauseAndRestore - + + container.addSubview(animationView) + NSLayoutConstraint.activate([ + animationView.leadingAnchor.constraint(equalTo: container.leadingAnchor), + animationView.trailingAnchor.constraint(equalTo: container.trailingAnchor), + animationView.topAnchor.constraint(equalTo: container.topAnchor), + animationView.bottomAnchor.constraint(equalTo: container.bottomAnchor) + ]) + + // 通过 Coordinator 保存引用,便于 updateUIView 控制播放 + context.coordinator.animationView = animationView + // 播放/暂停 if isPlaying { animationView.play() } else { animationView.pause() } - - return animationView + + return container } - func updateUIView(_ uiView: LottieAnimationView, context: Context) { + func updateUIView(_ uiView: UIView, context: Context) { + guard let animationView = context.coordinator.animationView else { return } // 根据 isPlaying 控制播放/暂停 if isPlaying { - if !uiView.isAnimationPlaying { - uiView.play() + if !animationView.isAnimationPlaying { + animationView.play() } } else { - if uiView.isAnimationPlaying { - uiView.pause() + if animationView.isAnimationPlaying { + animationView.pause() } } } + + // 使用 Coordinator 在 make/update 周期之间保存 animationView 引用 + class Coordinator { + var animationView: LottieAnimationView? + } + + func makeCoordinator() -> Coordinator { + Coordinator() + } } \ No newline at end of file