布景
手上有需求需求运用CDN资源来让Lottie做动画,但因为动画需求加载图片,而Lottie供给的初始化接口只能加载json装备,Github上的issues也没人回答,因而特地写下本文记录一下计划。
为了完成这个功用还把Lottie看了一遍也是醉了。。。
计划
首要需求清晰的一个点是假如你的Lottie资源带图片,那么直接运用LOTAnimationView的initWithContentsOfURL:办法是无法自动加载图片资源的。因为加载图片需求为LOTComposition设置baseURL,但经过url初始化animatonView时,因为json装备需求异步加载,所以该view的sceneModel为空,你无法直接设置,而view内部又没有加载完结的回调,因而只能经过监听sceneModel设置或许生成一个sceneModel传入这两种办法来完成Lottie图片资源加载。
以下介绍完成办法。
1. 为Lottie库新增LOTAnimationDelegate署理
首要需求完成LOTAnimationView的图片恳求署理办法。Lottie内部不会自行恳求图片,能够在LOTLayerContainer的_setImageForAsset:办法中经过署理办法的形式将图片恳求抛到外部完成。然后获取到图片后赋值给self.wrapperLayer.contents即可,示例如下。
- (void)_setImageForAsset:(LOTAsset *)asset {
...
[delegate animationView:asset.animationView fetchResourceWithURL:url completionHandler:^(UIImage * _Nullable image, NSError * _Nullable error) {
if (image) {
dispatch_async(dispatch_get_main_queue(), ^{
self.wrapperLayer.contents = (__bridge id _Nullable)(image.CGImage);
});
}
}];
...
}
- (void)animationView:(LOTAnimationView *)animationView fetchResourceWithURL:(NSURL *)url completionHandler:(LOTResourceCompletionHandler)completionHandler {
[CDNService requestLottieImageWithURL:url completion:^(UIImage * _Nullable image, NSError * _Nullable error) {
if (completionHandler) {
completionHandler(image, error);
}
}];
}
2. 生成LOTComposition
其次,因为外部事务无法直接感知LOTAnimationView内部生成的LOTComposition的时机,因而能够选择自己生成它,并设置baseURL。
+ (void)requestLottieModelWithURL:(NSURL *)url completion:(void(^)(LOTComposition * _Nullable sceneModel, NSError * _Nullable error))completion {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) {
NSData *animationData = [NSData dataWithContentsOfURL:url];
if (!animationData) {
return;
}
NSError *error;
NSDictionary *animationJSON = [NSJSONSerialization JSONObjectWithData:animationData options:0 error:&error];
if (error || !animationJSON) {
if (completion) {
completion(nil, error);
}
return;
}
LOTComposition *model = [[LOTComposition alloc] initWithJSON:animationJSON withAssetBundle:[NSBundle mainBundle]];
dispatch_async(dispatch_get_main_queue(), ^(void) {
[[LOTAnimationCache sharedCache] addAnimation:model forKey:url.absoluteString];
//留意,这里的baseURL是你的恳求path,需求依据你的事务情况自行设置
model.baseURL = @"https://os.xxx.cn/lottie/animation/";
model.cacheKey = url.absoluteString;
if (completion) {
completion(model, nil);
}
});
});
}
需求留意的是LOTComposition的baseURL设置,不只需求检查Lottie的json装备文件,还需求关注服务端存储Lottie文件的路径。
假定你有一个叫animation的Lottie资源,那么请先打开装备json观察assets.u的值。这里假定assets.u为”images/”,则你需求在服务端存储的文件结构如下:
- animation
- data.json
- images
- img_0.png
- img_1.png
此刻,假如json的恳求url是https://os.xxx.cn/lottie/animation/data.json
,那么需求给LOTComposition的baseURL设置为https://os.xxx.cn/lottie/animation/
。
3. 初始化LOTAnimationView
最后只需求恳求资源并传给LOTAnimationView即可。
- (LOTAnimationView *)animationView {
if (!_animationView) {
//留意,假如想先初始化view再恳求资源,不要运用new或许init来初始化
_animationView = [[LOTAnimationView alloc] initWithFrame:CGRectZero];
_animationView.animationDelegate = self;
NSURL *url = [NSURL URLWithString:@"https://os.xxx.cn/lottie/animation/data.json"];
//恳求json装备,生成LOTComposition后传给view
@weakify(self);
[CCDNService requestLottieModelWithURL:url completion:^(LOTComposition * _Nullable sceneModel, NSError * _Nullable error) {
@strongify(self);
self.animationView.sceneModel = sceneModel;
}];
}
return _animationView;
}