84 lines
2.8 KiB
Swift
84 lines
2.8 KiB
Swift
import SwiftUI
|
||
import Lottie
|
||
|
||
struct LottieView: UIViewRepresentable {
|
||
let name: String
|
||
let loopMode: LottieLoopMode
|
||
let animationSpeed: CGFloat
|
||
let isPlaying: Bool
|
||
|
||
init(name: String, loopMode: LottieLoopMode = .loop, animationSpeed: CGFloat = 1.0, isPlaying: Bool = true) {
|
||
self.name = name
|
||
self.loopMode = loopMode
|
||
self.animationSpeed = animationSpeed
|
||
self.isPlaying = isPlaying
|
||
}
|
||
|
||
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 container
|
||
}
|
||
|
||
func updateUIView(_ uiView: UIView, context: Context) {
|
||
guard let animationView = context.coordinator.animationView else { return }
|
||
// 根据 isPlaying 控制播放/暂停
|
||
if isPlaying {
|
||
if !animationView.isAnimationPlaying {
|
||
animationView.play()
|
||
}
|
||
} else {
|
||
if animationView.isAnimationPlaying {
|
||
animationView.pause()
|
||
}
|
||
}
|
||
}
|
||
|
||
// 使用 Coordinator 在 make/update 周期之间保存 animationView 引用
|
||
class Coordinator {
|
||
var animationView: LottieAnimationView?
|
||
}
|
||
|
||
func makeCoordinator() -> Coordinator {
|
||
Coordinator()
|
||
}
|
||
} |