Como o iOS permite que Lottie use recursos de rede para animação

fundo

Existe a necessidade de usar recursos CDN para deixar Lottie fazer animações, mas como as animações precisam carregar imagens, a interface de inicialização fornecida por Lottie só pode carregar configurações json e ninguém respondeu aos problemas no Github, então escrevi este artigo para registre a solução.

Para conseguir essa função, até assisti Lottie novamente e estava bêbado. . .

plano

O primeiro ponto que precisa ser esclarecido é que, se o recurso Lottie tiver imagens, o uso direto do método initWithContentsOfURL: de LOTAnimationView não poderá carregar automaticamente o recurso de imagem. Como o carregamento de imagens precisa definir baseURL para LOTComposition, mas ao inicializar animatonView por meio de url, como a configuração json precisa ser carregada de forma assíncrona, o sceneModel da exibição está vazio, você não pode defini-lo diretamente e não há retorno de chamada para conclusão do carregamento dentro a exibição, portanto, você só pode passar as configurações de Listen to sceneModel ou gerar um sceneModel para passar dessas duas maneiras para realizar o carregamento do recurso de imagem Lottie.

A implementação é descrita a seguir.

1. Adicione o agente LOTAnimationDelegate para a biblioteca Lottie

Primeiro, você precisa implementar o método de proxy de solicitação de imagem de LOTAnimationView. Lottie não solicita imagens internamente e pode usar o método proxy no método _setImageForAsset: de LOTLayerContainer para enviar a solicitação de imagem para fora para implementação. Em seguida, obtenha a imagem e atribua-a a self.wrapperLayer.contents, o exemplo é o seguinte.

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

Em segundo lugar, como o negócio externo não pode perceber diretamente o tempo do LOTComposition gerado dentro do LOTAnimationView, ele pode optar por gerá-lo sozinho e definir o 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);
            }
        });
    });
}
复制代码

Deve-se observar que a configuração baseURL de LOTComposition não precisa apenas visualizar o arquivo de configuração json de Lottie, mas também precisa prestar atenção ao caminho onde o servidor armazena os arquivos 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;
}
复制代码

Acho que você gosta

Origin juejin.im/post/7195449060201857084
Recomendado
Clasificación