lottie-react-native がアニメーションを描画する仕組み（ネイティブブリッジまで）

私が所属する会社では [lottie-react-native](https://github.com/react-native-community/lottie-react-native) というライブラリを使用してアニメーションを描画しています。

私は lottie-react-native の導入を担当したこともあり、ライブラリの使い方については把握しています。しかし、アニメーションが描画される仕組みは理解できていないので、調査してみることにします。

## lottie-react-native は各 OS の Lottie ライブラリを利用
lottie-react-native を利用してアニメーションを描画する際は、 `LottieView` コンポーネントを使用します。

```react:サンプルコード
import React from 'react';
import LottieView from 'lottie-react-native';

export default class BasicExample extends React.Component {
  render() {
    return <LottieView source={require('./animation.json')} autoPlay loop />;
  }
}
```

ソースコードを読むと、ネイティブ層で実装している `LottieAnimationView` が `LottieView` コンポーネントの内部で呼び出されていることがわかります。

```react:/src/js/LottieView.js
const NativeLottieView = SafeModule.component({
  viewName: 'LottieAnimationView',
  mockComponent: View,
});
```

`iOS` 側の `LottieAnimationView` は `AnimationViewManagerModule.swift` というファイルで実装されています。そのファイルでは [lottie-ios](https://github.com/airbnb/lottie-ios) の `Lottie` モジュールがインポートされています。

```swift:/src/ios/LottieReactNative/AnimationViewManagerModule.swift
import Lottie

@objc(LottieAnimationView)
class AnimationViewManagerModule: RCTViewManager {
```

`Android` 側の `LottieAnimationView` は `LottieAnimationViewManager.java` というファイルで実装されています。そのファイルでは [lottie-android](https://github.com/airbnb/lottie-android) の `LottieAnimationView` クラスがインポートされています。

```java:/src/android/src/main/java/com/airbnb/android/react/lottie/LottieAnimationViewManager.java
import com.airbnb.lottie.LottieAnimationView;
...
  private static final String REACT_CLASS = "LottieAnimationView";
```

つまり、 `lottie-react-native` は各 OS の Lottie ライブラリを利用して、アニメーションを描画していることがわかります。

## ネイティブブリッジ実装箇所までの辿り方
アニメーションの描画は `LottieView` コンポーネントを利用するので、それが実装されている `/src/js/LottieView.js` を確認しました。 => [GitHub](https://github.com/react-native-community/lottie-react-native/blob/master/src/js/LottieView.js)

アニメーションを描画しているのは `render()` で `return()` しているコンポーネントです。
実装を見てみると、 `AnimatedNativeLottieView` というコンポーネントが返っています。

```react:/src/js/LottieView.js
    return (
      <View style={[aspectRatioStyle, sizeStyle, style]}>
        <AnimatedNativeLottieView
          ref={this.refRoot}
          {...rest}
          speed={speed}
          style={[aspectRatioStyle, sizeStyle || { width: '100%', height: '100%' }, style]}
          sourceName={sourceName}
          sourceJson={sourceJson}
          onAnimationFinish={this.onAnimationFinish}
        />
      </View>
    );
```

`AnimatedNativeLottieView` は `React Native` の `Animated.createAnimatedComponent` を使用して、 animatable になったコンポーネントであることがわかりました。 => [公式ドキュメント](https://facebook.github.io/react-native/docs/animated#createanimatedcomponent)

```react:/src/js/LottieView.js
const AnimatedNativeLottieView = Animated.createAnimatedComponent(NativeLottieView);
```

引数に渡している `NativeLottieView` が、ネイティブ層で定義されている `LottieAnimationView` であることがわかり、ネイティブブリッジしていることがわかりました。

```react:/src/js/LottieView.js
const NativeLottieView = SafeModule.component({
  viewName: 'LottieAnimationView',
  mockComponent: View,
});
```

## 次回は各 OS の Lottie ライブラリを調査
今回の調査で、アニメーションを描画する仕組みが各 OS の Lottie ライブラリで実装されていることがわかりました。

アニメーションを描画する Lottie の仕組みを探るため、次回は各 OS の Lottie ライブラリである lottie-ios と lottie-android を調査しようと思います。