項目中使用動畫,開始采用Gif動畫,發(fā)現(xiàn)Gif動畫文件1.5M 在線加載慢登夫,改為json動畫使用Lottie 第三方庫加載對比分析,優(yōu)缺點分析主要兩點:
1.json文件只有400k 對比gif文件包少了三分之二 蝗敢;
2.UI效果對比gif顯示放大有齒輪和鏤空的失真日缨,json動畫UI還原度高,但是json動畫設(shè)計轉(zhuǎn)出json文件更麻煩些家卖;
場景分析:
1.gif動畫適合小圖標(biāo)動畫效果
2.json動畫適合大圖動畫效果
Gif demo代碼片段
/// 顯示本地 GIF 圖片
? ? func showLocalGIF(name: String?) {
? ? ? ? guard?let?name = name?else?{?return?}
? ? ? ? self.gifImage=GIFImage(named: name)
? ? }
json 動畫代碼實例盆犁,采用pod 'lottie-ios', '3.2.3'版本 ?,本地json文件顯示動畫:
let animationView = AnimationView(name: "inviteData")
? ? ? ? animationView.frame = CGRect(x: 0, y: 0, width: (kScreenWidth - 80)*kWidthScale, height:((kScreenWidth - 80)*1225/879)*kWidthScale)
? ? ? ? imageBackVIew.addSubview(animationView)
? ? ? ? animationView.contentMode = .scaleToFill
? ? ? ? animationView.loopMode = .loop
? ? ? ? animationView.play()
? ? ? ? animationView.play { (isFinished) in
?? ? ? ?}
在線加載json文件采用兩種方式:
一、在線加載json文件,采用pod 'lottie-ios', '3.2.3'版本 ?網(wǎng)頁可直接打卡json文件:
if let url = URL(string: "https://yangtuo.oss-cn-hangzhou.aliyuncs.com/mall2c/happy_gift.json") {
????????giftAnimaView = AnimationView(url: url, imageProvider: self, closure: { [weak self] (error) in
?????????????guard let `self` = self else { return }
? ? ? ? ? ? ? ? if let _ = error {
? ? ? ? ? ? ? ? ? ? print("網(wǎng)絡(luò)動畫加載失敗~~")
? ? ? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? ? ? /// 獲取是異步的篡九,所以需要等待動畫獲取完成
? ? ? ? ? ? ? ? ? ? self.giftAnimaView.play { (finished) in
????????????????}
??}
? ? ? ? ? ? ? ? }, animationCache: self)
? ? ? ? ? ? giftAnimaView.frame = CGRect(x: 0, y: 0, width: (kScreenWidth - 80)*kWidthScale, height:((kScreenWidth - 80)*1225/879)*kWidthScale)
? ? ? ? ? ? giftAnimaView.contentMode = .scaleToFill
? ? ? ? ? ? giftAnimaView.loopMode = .loop
? ? ? ? ? ? imageBackVIew.addSubview(giftAnimaView)
? ? ? ? }
二谐岁、在線加載json文件,采用pod 'lottie-ios', '3.2.3'版本 ?需下載json文件:
LPLottieResourceManager.shared.loadBundleProvider(123412,"\(BackGround)") {[weakself] (jsonpath, provider)in
?? ? ? ? ? ? guard?let`self` =self?else{return}
?? ? ? ? ? ? guard?let? jsonfile = json path?else{return}
? ? ? ? ? ? DeLog("jsonFile:\(jsonfile)")
?? ? ? ? ? ? self.giftAnimaView=AnimationView.init(filePath:jsonfile)
? ? ? ? ? ? ?iflet? prov = provider {
?? ? ? ? ? ? ? ? self.giftAnimaView.imageProvider= prov
?? ? ? ? ? ? }
? ? ? ? ? ? self.giftAnimaView.frame = CGRect(x: 0, y: 0, width: (kScreenWidth - 80)*kWidthScale, height:((kScreenWidth - 80)*1225/879)*kWidthScale)
? ? ? ? ? ? self.giftAnimaView.contentMode = .scaleToFill
? ? ? ? ? ? self.giftAnimaView.loopMode = .loop
? ? ? ? ? ? self.giftAnimaView.play()
? ? ? ? ? ? self.imageBackVIew.addSubview(self.giftAnimaView)
?? ? ? ? }
LPLottieResourceManager 類繼承NSObject,實現(xiàn)思路先通過Moya下載本地資源包,通過資源包打卡在線加載:
importUIKit
importFoundation
//import ZipArchive
import Moya
importLottie
typealiaslottieResultBlock= (_ jsonfullpath:String?,_ provider:BundleImageProvider?) ->Void
class LPLottieResourceManager:NSObject {
? ? let? filepath? =NSHomeDirectory() + "/Documents/LiveKit/GiftFile"
? ? static? let? shared = LPLottieResourceManager()
? ? override init() {
? ? ? ? super.init()
? ? ? ? ifFileManager.default.fileExists(atPath:filepath) {
? ? ? ? ? ? print("禮物 目錄存在")
? ? ? ? }
? ? ? ? else{
? ? ? ? ? ? try! FileManager.default.createDirectory(atPath: filepath,
?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? withIntermediateDirectories:true,attributes:nil)
? ? ? ? }
? ? }
? ? /// 加載lottie特效
? ? /// - Parameters:
? ? ///? - giftId: 特效id
? ? ///? - downloadurl: 特效下載地址
? ? ///? - animationresult: 特效 images目錄
? ? func? loadBundleProvider(_giftId:Int,_downloadurl:String,_animationresult:@escapinglottieResultBlock) {
? ? ? ? letfullpath =filepath+"/\(giftId)/data.json"
? ? ? ? letimgprovider =filepath+"/\(giftId)/images"
? ? ? ? varjsonpath:String?=nil
? ? ? ? ifFileManager.default.fileExists(atPath: fullpath) {
? ? ? ? ? ? jsonpath = fullpath
? ? ? ? ? ? if? FileManager.default.fileExists(atPath: imgprovider)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? let? provider =BundleImageProvider.init(bundle:Bundle.main,searchPath: imgprovider)
? ? ? ? ? ? ? ? animationresult(jsonpath,provider)
? ? ? ? ? ? }else{
? ? ? ? ? ? ? ? animationresult(jsonpath,nil)
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? ? ? //網(wǎng)絡(luò)下載 并解壓
? ? ? ? else{
? ? ? ? ? ? let? giftpath =filepath+"/\(giftId)"
? ? ? ? ? ? letassetName =? "\(giftId)"
? ? ? ? ? ? jsonpath = giftpath +"/data.json"
? ? ? ? ? ? let? urladdress? = downloadurl
? ? ? ? ? ? //通過Moya進行下載
? ? ? ? ? ? MyServiceProvider.request(.downloadGiftLottie(downloadurl:urladdress,giftDirectoryName: assetName)) { result in
? ? ? ? ? ? ? ? switchresult {
? ? ? ? ? ? ? ? case.success:
? ? ? ? ? ? ? ? ? ? letlocalLocation:URL= DefaultDownloadDir.appendingPathComponent(assetName)
? ? ? ? ? ? ? ? ? ? print("下載完畢伊佃!保存地址:\(localLocation)")
? ? ? ? ? ? ? ? ? ? if? urladdress.contains(".zip") {
? ? ? ? ? ? ? ? ? ? ? ? let? urlpath =URL.init(fileURLWithPath:self.filepath+"/\(giftId).zip")
? ? ? ? ? ? ? ? ? ? ? ? do{
? ? ? ? ? ? ? ? ? ? ? ? ? ? try? ? ? FileManager.default.createDirectory(atPath:self.filepath+"/\(giftId)",withIntermediateDirectories:true,attributes:nil)
? ? ? ? ? ? ? ? ? ? ? ? ? ? //得到正確的資源包? 12312/ data images
? ? ? ? ? ? ? ? ? ? ? ? ? ? if? FileManager.default.fileExists(atPath: imgprovider)
? ? ? ? ? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? let? provider =BundleImageProvider.init(bundle:Bundle.main,searchPath: imgprovider)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? animationresult(jsonpath,provider)
? ? ? ? ? ? ? ? ? ? ? ? ? ? }else{
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? animationresult(jsonpath,nil)
? ? ? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ? ? ? //? ? ? ? ? ? ? ? ? ? ? ? print(zipurl)
? ? ? ? ? ? ? ? ? ? ? ? }catch(leterr) {
? ? ? ? ? ? ? ? ? ? ? ? ? ? print("解壓失敗")
? ? ? ? ? ? ? ? ? ? ? ? ? ? animationresult(nil,nil)
? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? elseifurladdress.contains(".json") {
? ? ? ? ? ? ? ? ? ? ? ? do{
? ? ? ? ? ? ? ? ? ? ? ? ? ? try? ? ? FileManager.default.createDirectory(atPath:self.filepath+"/\(giftId)",withIntermediateDirectories:true,attributes:nil)
? ? ? ? ? ? ? ? ? ? ? ? ? ? try? FileManager.default.moveItem(atPath:self.filepath+"/data.json",toPath: giftpath +"/data.json")
? ? ? ? ? ? ? ? ? ? ? ? ? ? animationresult(jsonpath,nil)
? ? ? ? ? ? ? ? ? ? ? ? }catch(leterr) {
? ? ? ? ? ? ? ? ? ? ? ? ? ? debugPrint("文件出錯\(err)")
? ? ? ? ? ? ? ? ? ? ? ? ? ? animationresult(nil,nil)
? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ??caselet.failure(error):
? ? ? ? ? ? ? ? ? ? print(error)
? ? ? ? ? ? ? ? ? ? animationresult(nil,nil)
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? }
? ? }
}
//MARK:單獨組件處理下載
//初始化請求的provider
let MyServiceProvider = MoyaProvider<DownLoadService>()
//請求分類
public enum DownLoadService {
? ? casedownloadGiftLottie(downloadurl:String,giftDirectoryName:String)//下載文件
}
//請求配置
extension DownLoadService: TargetType {
? ? publicvarpath:String{
? ? ? ? return""
? ? }
? ? //服務(wù)器地址
? ? publicvarbaseURL:URL{
? ? ? ? switchself{
? ? ? ? case.downloadGiftLottie(let? url , _ ):
? ? ? ? ? ? returnURL.init(string: url)!
? ? ? ? default:
? ? ? ? ? ? return URL(string: "http://www.baidu.com")!
? ? ? ? }
? ? }
? ? //請求類型
? ? publicvarmethod: Moya.Method{
? ? ? ? return.get
? ? }
? ? //請求任務(wù)事件(這里附帶上參數(shù))
? ? publicvartask:Task{
? ? ? ? switchself{
? ? ? ? case.downloadGiftLottie(let? downloadurl ,letsaveName):
? ? ? ? ? ? varlocalLocation:URL!
? ? ? ? ? ? ifdownloadurl.contains(".zip") {
? ? ? ? ? ? ? ? localLocation = DefaultDownloadDir.appendingPathComponent(saveName+".zip")
? ? ? ? ? ? }elseifdownloadurl.contains(".json") {
? ? ? ? ? ? ? ? localLocation = DefaultDownloadDir.appendingPathComponent("data.json")
? ? ? ? ? ? }
? ? ? ? ? ? //
? ? ? ? ? ? letdownloadDestination:DownloadDestination= { _, _in
? ? ? ? ? ? ? ? return(localLocation, .removePreviousFile) }
? ? ? ? ? ? return.downloadDestination(downloadDestination)
? ? ? ? }
? ? }
? ? //是否執(zhí)行Alamofire驗證
? ? public?var?validate:Bool{
? ? ? ? return false
? ? }
? ? //這個就是做單元測試模擬的數(shù)據(jù)窜司,只會在單元測試文件中有作用
? ? public?var?sampleData:Data{
? ? ? ? return"{}".data(using:String.Encoding.utf8)!
? ? }
? ? //請求頭
? ? publicvarheaders: [String:String]? {
? ? ? ? returnnil
? ? }
}
//定義下載的DownloadDestination(不改變文件名,同名文件不會覆蓋)
privateletDefaultDownloadDestination:DownloadDestination= { temporaryURL, responsein
? ? return(DefaultDownloadDir.appendingPathComponent(response.suggestedFilename!), [.removePreviousFile])
}
//默認(rèn)下載保存地址(用戶文檔目錄)
let DefaultDownloadDir: URL = {
? ? return? URL(fileURLWithPath: LPLottieResourceManager.shared.filepath)
}()