背景
手上有需求需要使用cdn资源来让lottie做动画,但由于动画需要加载图片,而lottie提供的初始化接口只能加载json配置,github上的issues也没人回答,因此特地写下本文记录一下方案。
为了实现这个功能还把lottie看了一遍也是醉了。。。
方案
首先需要明确的一个点是如果你的lottie资源带图片,那么直接使用lotanimationview的initwithcontentsofurl:方法是无法自动加载图片资源的。因为加载图片需要为lotcomposition设置baseurl,但通过url初始化animatonview时,由于json配置需要异步加载,所以该view的scenemodel为空,你无法直接设置,而view内部又没有加载完成的回调,因此只能通过监听scenemodel设置或者生成一个scenemodel传入这两种方式来实现lottie图片资源加载。
以下介绍实现方式。
1. 实现lotanimationdelegate代理
首先需要实现lotanimationview的图片请求代理方法。lottie内部不会自行请求图片,而是通过代理方法的形式将图片请求抛到外部实现。
- (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是os.xxx.cn/lottie/anim… ,那么需要给lotcomposition的baseurl设置为os.xxx.cn/lottie/anim… 。
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; }
以上就是ios如何让lottie使用网络资源做动画的详细内容,更多关于ios lottie网络资源做动画的资料请关注代码网其它相关文章!
发表评论