iOS は Lottie がアニメーションにネットワーク リソースを使用できるようにする方法

バックグラウンド

Lottie にアニメーションをさせるには CDN リソースを使用する必要がありますが、アニメーションは画像をロードする必要があるため、Lottie が提供する初期化インターフェイスは json 構成しかロードできず、Github で誰も問題に答えていないため、この記事を書いた解決策を記録します。

この機能を達成するために、ロッティをもう一度見て酔いました。. .

プラン

明確にする必要がある最初の点は、Lottie リソースに画像がある場合、LOTAnimationView の initWithContentsOfURL: メソッドを直接使用しても画像リソースを自動的にロードできないことです。画像の読み込みには LOTComposition の baseURL を設定する必要がありますが、animatonView を url で初期化する場合、json 構成を非同期で読み込む必要があるため、ビューの sceneModel は空であり、直接設定することはできず、内部に読み込み完了のためのコールバックがありません。したがって、これらの 2 つの方法で渡す SceneModel の設定に Listen を渡すか、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 の生成

第 2 に、外部のビジネスは 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;
}
复制代码

おすすめ

転載: juejin.im/post/7195449060201857084