How does iOS allow Lottie to use network resources for animation

background

There is a need to use CDN resources to let Lottie do animations, but because animations need to load images, the initialization interface provided by Lottie can only load json configurations, and no one has answered the issues on Github, so I wrote this article to record the solution .

In order to achieve this function, I even watched Lottie again and was drunk. . .

plan

The first point that needs to be clarified is that if your Lottie resource has a picture, then directly using the initWithContentsOfURL: method of LOTAnimationView cannot automatically load the picture resource. Because loading pictures needs to set baseURL for LOTComposition, but when initializing animatonView through url, since the json configuration needs to be loaded asynchronously, the sceneModel of the view is empty, you cannot set it directly, and there is no callback for loading completion inside the view, so you can only pass Listen to sceneModel settings or generate a sceneModel to pass in these two ways to realize Lottie image resource loading.

The implementation is described below.

1. Add LOTAnimationDelegate agent for Lottie library

First, you need to implement the image request proxy method of LOTAnimationView. Lottie does not request images internally, and can send image requests to the outside through proxy methods in the _setImageForAsset: method of LOTLayerContainer. Then get the picture and assign it to self.wrapperLayer.contents, the example is as follows.

- (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. Generate LOTComposition

Secondly, since external businesses cannot directly perceive the timing of the LOTComposition generated inside the LOTAnimationView, they can choose to generate it by themselves and set the 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);
            }
        });
    });
}
复制代码

It should be noted that the baseURL setting of LOTComposition not only needs to view Lottie's json configuration file, but also needs to pay attention to the path where the server stores Lottie files.

假设你有一个叫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;
}
复制代码

Guess you like

Origin juejin.im/post/7195449060201857084