SVGAParsePlayer
是一个便捷SVGA播映器,是对SVGAPlayer的二次封装。
SVGAParsePlayer_Demo
Feature:
✅ 内置SVGA解析器;
✅ 带有播映状况且可操控;
✅ 可自界说下载器;
✅ 防止重复加载;
✅ 兼容 OC & Swift;
✅ API简略易用。
SVGAPlayer
是个很老的第三方库了,作者很久没有更新,运用起来挺费事的,本来的运用办法:
let player = SVGAPlayer()
override func viewDidLoad() {
super.viewDidLoad()
player.frame = CGRect(x: 100, y: 100, width: 100, height: 100)
view.addSubview(player)
// 创建 SVGA 动画解析器
let parser = SVGAParser()
// 加载 SVGA 动画文件
parser.parse(withNamed: "your_animation_file", in: nil) { [weak self] videoItem in
guard let self, videoItem else { return }
// 将 SVGA 动画加载到播映器中
self.player.videoItem = videoItem
// 开端播映动画
self.player.startAnimation()
}
}
老实说,功能没有Lottie好,可是没办法,项目要用。为了运用起来愈加便利,于是乎在此基础上进行二次封装。
根本运用
SVGAParsePlayer
本身便是继承自SVGAPlayer
,根本设置跟之前相同即可,主要是API的运用不相同(变得愈加易用)。
加载并播映:
player.play("your_animation_path", fromFrame: 0, isAutoPlay: true)
-
fromFrame
: 从第几帧开端 -
isAutoPlay
: 加载完结后是否主动开端播映
内部会主动调用SVGAParser
进行「长途/本地」SVGA资源的加载,所以调用该办法后并不会立马播映,会有加载的过程。
加载后能够挑选是否主动播映,具体的状况能够恪守SVGAParsePlayerDelegate
,能够收到状况产生改动的回调:
/// 状况产生改动的回调
func svgaParsePlayer(_ player: SVGAParsePlayer,
statusDidChanged status: SVGAParsePlayerStatus,
oldStatus: SVGAParsePlayerStatus)
别的加载的失利和完结SVGAParsePlayerDelegate
也有对应的回调:
/// SVGA不知道来源
func svgaParsePlayer(_ player: SVGAParsePlayer,
unknownSvga source: String)
/// SVGA资源加载失利
func svgaParsePlayer(_ player: SVGAParsePlayer,
svga source: String,
dataLoadFailed error: Error)
/// 加载的SVGA资源解析失利
func svgaParsePlayer(_ player: SVGAParsePlayer,
svga source: String,
dataParseFailed error: Error)
/// 本地SVGA资源解析失利
func svgaParsePlayer(_ player: SVGAParsePlayer,
svga source: String,
assetParseFailed error: Error)
/// SVGA资源解析成功
func svgaParsePlayer(_ player: SVGAParsePlayer,
svga source: String,
parseDone entity: SVGAVideoEntity)
-
SVGAParsePlayerDelegate
的办法都是可选的,还有其他的办法具体能够看看Demo。
假如现已有现成的SVGAVideoEntity
目标,就能够直接运用该目标进行播映:
let entity: SVGAVideoEntity = ...
player.play(with: entity, fromFrame: 0, isAutoPlay: true)
- 运用这种办法播映的话,
svgaSource
则为SVGAVideoEntity
目标的内存地址。
加载优化
加载长途的SVGA资源,内部是运用SVGAParser
自带的下载办法,假如需求自己界说下载办法(例如加载缓存的资源),能够自界说下载器:
SVGAParsePlayer.downloader = { svgaSource, success, failure in
guard let url = URL(string: svgaSource) else {
failure(NSError(domain: "SVGAParsePlayer", code: -1, userInfo: [NSLocalizedDescriptionKey: "途径过错"]))
return
}
Task {
do {
let (data, _) = try await URLSession.shared.data(from: url)
await MainActor.run { success(data) }
} catch {
await MainActor.run { failure(error) }
}
}
}
- 完成
SVGAParsePlayer.downloader
这个闭包即可。
阐明一点,假如播映相同的资源途径,并且该资源正在加载或许现已加载好了,是不会重复去加载的。内部是依据资源途径来判断是否同一个SVGA资源,除非换成新的资源途径,就会清除上一个资源去加载新的资源,这是为了保证同一个资源不会做重复的加载操作。
注意:内部是经过判定资源途径是否带有http://
和https://
的前缀,才去调用下载器进行下载的,不然就会运用本地资源加载的办法。
假如想完全由自己操控加载办法,能够去完成SVGAParsePlayer.loader
这个闭包:
SVGAParsePlayer.loader = { svgaSource, success, failure, forwardDownload, forwardLoadAsset in
// 判断是不是磁盘的SVGA
guard FileManager.default.fileExists(atPath: svgaSource) else {
if svgaSource.hasPrefix("http://") || svgaSource.hasPrefix("https://") {
// 调用SVGAParsePlayer内部的长途加载办法(假如完成了SVGAParsePlayer.downloader就调用该闭包)
forwardDownload(svgaSource)
} else {
// 调用SVGAParsePlayer内部的本地资源加载办法
forwardLoadAsset(svgaSource)
}
return
}
// 加载磁盘的SVGA
do {
let data = try Data(contentsOf: URL(fileURLWithPath: svgaSource))
success(data)
} catch {
failure(error)
}
}
- forwardDownload:本来
SVGAParsePlayer
内部的长途加载办法(假如完成了SVGAParsePlayer.downloader
就调用该闭包) - forwardLoadAsset::本来
SVGAParsePlayer
内部的本地资源加载办法
其他的API和设置
/// 播映当时SVGA(从当时所在帧开端)
player.play()
/// 播映当时SVGA
/// - Parameters:
/// - fromFrame: 从第几帧开端
player.play(fromFrame: 0)
/// 暂停播映
player.pause()
/// 重置当时SVGA(回到开头)
/// - Parameters:
/// - isAutoPlay: 是否主动开端播映
player.reset(isAutoPlay: false)
/// 中止播映
/// - Parameters:
/// - isClear: 是否清空SVGA资源(清空的话下次播映就需求重新加载资源)
player.stop(isClear: false)
- 由于调用播映的办法并不会立马就播映,假如在加载的过程中再次调用播映的办法,但
fromFrame
和isAutoPlay
不相同,那么fromFrame
和isAutoPlay
会以最新的设置来进行后续的操作。
可定制化的设置:
/// 是否带动画过渡
/// - 为`true`则会在「替换SVGA」和「播映/中止」的场景中带有淡入淡出的效果
var isAnimated = false
/// 是否在空闲/中止状况时隐藏本身
var isHidesWhenStopped = false
/// 是否启用内存缓存(SVGAParser)
var isEnabledMemoryCache = false
互斥的API
由于SVGAParsePlayer
本身继承自SVGAPlayer
,为了避免产生过错,不要调用SVGAPlayer
本来的这些API:
@property (nonatomic, weak) id<SVGAPlayerDelegate> delegate;
- (void)startAnimation;
- (void)startAnimationWithRange:(NSRange)range reverse:(BOOL)reverse;
- (void)pauseAnimation;
- (void)stopAnimation;
- (void)clear;
- (void)stepToFrame:(NSInteger)frame andPlay:(BOOL)andPlay;
- (void)stepToPercentage:(CGFloat)percentage andPlay:(BOOL)andPlay;
- 本来的
delegate
给到本身恪守了,假如需求监听曾经的代理办法,那就运用myDelegate
,也便是SVGAParsePlayerDelegate
,包含了本来delegate
的办法还有上面的那几个回调办法。
已然不想运用本来的API,为什么要运用继承SVGAPlayer
的办法?
- 首先为了让根本设置跟之前相同;
- 其次期望跟之前相同当做一个UIView来运用,但不想再套一层UIView,为了尽可能削减图层的数量。
最后
介绍就这么多了,总的来说SVGAPlayer比照Lottie
轻量一些,比较适合动画数量少的场景。但假如需求许多且复杂的场景,我个人愈加引荐Lottie,究竟架构和功能要比SVGAPlayer
好许多,最重要是Lottie
一直都有维护和更新,而SVGAPlayer
现已不更新了。
而我的SVGAParsePlayer
只是在SVGAPlayer
的基础上做了「加载防重」和「API简化」,假如需求运用,能够到SVGAParsePlayer_Demo中直接CV代码(SVGAParsePlayer.swift和SVGAParsePlayer+.swift这两个文件)到自己工程里面就好了。