Files
uniapp-im-shop/uni_modules/tuikit-atomic-x/utssdk/app-ios/swift/SVGAAnimationView.swift
2026-01-12 17:52:15 +08:00

120 lines
4.1 KiB
Swift

import UIKit
import DCloudUTSFoundation
import SVGAPlayer
public class SVGAAnimationView: UIView {
private var playerView: SVGAPlayer?
private var svgaDelegate : SVGAAnimationViewDelegate?
private func cleanupOldPlayer() {
playerView?.removeFromSuperview()
playerView?.delegate = nil
playerView = nil
}
public func setDelegate(_ delegate : SVGAAnimationViewDelegate){
self.svgaDelegate = delegate
}
public func startAnimation(_ playUrl: String) {
console.log("======startAnimation, playUrl: ", playUrl)
guard isSVGAFile(url: playUrl) else {
console.error("======startAnimation error, playUrl is not svga")
self.svgaDelegate?.onFinished()
return
}
cleanupOldPlayer()
let player = SVGAPlayer(frame: bounds)
player.contentMode = .scaleAspectFill
player.delegate = self
player.loops = 1
addSubview(player)
player.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
player.leadingAnchor.constraint(equalTo: leadingAnchor),
player.trailingAnchor.constraint(equalTo: trailingAnchor),
player.topAnchor.constraint(equalTo: topAnchor),
player.bottomAnchor.constraint(equalTo: bottomAnchor)
])
self.playerView = player //
//
DispatchQueue.global().async { [weak self] in
guard let self = self else { return }
let url: URL?
if playUrl.hasPrefix("http://") || playUrl.hasPrefix("https://") {
url = URL(string: playUrl)
} else {
url = URL(fileURLWithPath: playUrl)
}
guard let validUrl = url,
let animationData = try? Data(contentsOf: validUrl) else {
DispatchQueue.main.async {
self.cleanupOldPlayer()
console.error("======startAnimation error, url parse error")
self.svgaDelegate?.onFinished()
}
return
}
let parser = SVGAParser()
parser.parse(with: animationData, cacheKey: validUrl.lastPathComponent) { [weak self] videoItem in
DispatchQueue.main.async {
console.error("======startAnimation begin")
guard let self = self else { return }
self.playerView?.videoItem = videoItem
self.playerView?.startAnimation()
}
} failureBlock: { [weak self] error in
DispatchQueue.main.async {
console.error("======startAnimation failed")
self?.cleanupOldPlayer()
self?.svgaDelegate?.onFinished()
}
}
}
}
public func stopAnimation() {
DispatchQueue.main.async { [weak self] in
guard let self = self else { return }
self.playerView?.stopAnimation()
//
self.playerView?.removeFromSuperview()
self.playerView?.delegate = nil
//
self.playerView = nil
}
}
private func isSVGAFile(url: String) -> Bool {
guard let urlObj = URL(string: url) else { return false }
let svgaExtension = "svga"
return urlObj.pathExtension.lowercased() == svgaExtension
}
}
// MARK: - SVGAPlayerDelegate
extension SVGAAnimationView: SVGAPlayerDelegate {
public func svgaPlayerDidFinishedAnimation(_ player: SVGAPlayer) {
UIView.animate(withDuration: 0.2, animations: {
player.alpha = 0
}) { _ in
player.removeFromSuperview()
self.cleanupOldPlayer()
console.error("======startAnimation, onFinished")
self.svgaDelegate?.onFinished()
}
}
}
public protocol SVGAAnimationViewDelegate: AnyObject {
func onFinished()
}