Lottieを使ってReactNativeアプリにアニメーションを追加する

## この記事は何か？
**バージョンが 0.59 よりも前** の `React Native` アプリに、 `Lottie` を利用して `Adobe After Effects` で作成したアニメーションを組み込んだときの話をまとめた記事です。

**対象読者**

- `React Native` アプリにアニメーションを組み込みたい方
- `React Native` アプリにアニメーションを組み込もうとしてハマっている方
- `React Native` アプリに `Adobe After Effects` で自作したアニメーションを組み込んでもらおうとしている方

**※ ここでいう React Native は、バージョンが 0.59 よりも前のものを指します。**
※ 動作確認は Android 端末でしか行なっていません。
※ iOS 端末だと動作しない可能性があります。後ほど iOS 端末で動作確認を行い追記します。

## この記事のゴール
- バージョンが 0.59 よりも前の `React Native` アプリに `Adobe After Effects` で作成したアニメーションを組み込める

## 開発環境
### PC
- `macOS Mojave`: v10.14.4

### モバイル
- `Android`: v8.0.0
- `iOS`: v11.4.1

### React Native 関連
- `react`: v16.4.1
- `react-native`: **v0.56.1（ < 0.59）**
- `react-native-cli`: v2.0.1
- `node`: v8.3.0
- `npm`: v5.3.0
- `watchman`: v4.9.0

### Adobe After Effects 関連
- `Adobe After Effects CC 2019`: v16.1.1
- `Bodymovin`: v5.5.2

## Lottie とは
`Lottie` とは、 `Airbnb` が開発しており、 `Adobe After Effects` で作成されたアニメーションをリアルタイムでレンダリングする `iOS` 、 `Android` 、および `React Native` のライブラリです。

> Lottie is an iOS, Android, and React Native library that renders After Effects animations in real time, allowing apps to use animations as easily as they use static images.
> 
> 参考: https://airbnb.design/lottie/

## lottie-react-native とは
調査したところ、 [lottie-react-native](https://github.com/react-native-community/lottie-react-native) を利用すると `React Native` アプリに `Adobe After Effects` で作成したアニメーションを組み込むことができることがわかりました。

このライブラリは `Adobe After Effects` で作成したアニメーションを `Bodymovin` を使って `JSON` 化したものをアプリに組み込んでレンダリングしています。

> Lottie is a mobile library for Android and iOS that parses Adobe After Effects animations exported as JSON with bodymovin and renders them natively on mobile!
>
> 参考: https://github.com/react-native-community/lottie-react-native#lottie-for-react-native-ios-and-android

## アニメーション側の準備
`lottie-react-native` を使って `React Native` に `Adobe After Effects` で作成したアニメーションを組み込む場合、 `Bodymovin` という `Adobe After Effects` の拡張機能を追加して、アニメーションを `JSON` 化する必要があります。

参考: [Lottie 公式ドキュメント](http://airbnb.io/lottie/#/after-effects)

### 1. ZXP installer をインストールする
https://aescripts.com/learn/zxp-installer/ から `ZXP installer` をダウンロードしました。

![zxp_installer.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/186009/db2c8ae9-d740-13bc-ff06-d75b5c80003b.png)

### 2. Bodymovin をダウンロードする
https://github.com/airbnb/lottie-web/blob/master/build/extension/bodymovin.zxp から `Bodymovin` をダウンロードしました。

![bodymovin_download.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/186009/d6b3fea4-413f-02c8-86c2-e0fe2ec1abf7.png)

### 3. Bodymovin をインストールする
`ZXP installer` を使用してダウンロードした `Bodymovin` をインストールしました。

![bodymovin_install.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/186009/ee64aa23-4a54-25d3-6a04-bfccf214c0a7.png)

### 4. Bodymovin を Adobe After Effects で開く
メニューから `Window` > `Extensions` を選択すると、 `Bodymovin` という項目がありました。それをタップすると、 `Adobe After Effects` 上で `Bodymovin` が開きました。

![open_bodymovin.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/186009/12701398-9818-9336-8b3f-ce18a99e4015.png)

### 5. 作成したアニメーションを JSON 化する
`Bodymovin` を開いたら、 `JSON` 化するコンポジションの `selected` をチェックして、保存先を決めた後に、 `render` ボタンを押せば `JSON` ファイルがエクスポートされます。

![export_animation.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/186009/156ec4be-3cea-b457-bd4f-d365764a0593.png)

**注意**

`Bodymovin` のバージョンが v5.5 以上の場合は、 `JSON` ファイルを古いフォーマットでエクスポートする必要があるようです。

> Lottie 3.0 and Bodymovin 5.5 has some significant json optimizations that will save upwards of 1/3 on the json size and parse speed. However, you must be on 3.0 or enable "export as old format" in bodymovin settings.
>
> 参考: https://github.com/airbnb/lottie-android/issues/1177#issuecomment-481635211

私も `Android` 端末で `JSON` 化したアニメーションを実際にレンダリングする時に、アプリがクラッシュしてしまいました。

```エラー文
java.lang.IllegalStateException: Missing values for keyframe.
```

そこで、 `JSON` 化するときに `Bodymovin` の設定の `Export Old Json Format` をオンにしてから、エクスポートするようにしました。

> Theres an additional settings in the bodymovin' plugin before u render that u can select (Settings > Advanced > Export Old Json Format) and then it worked for me!
>
> 参考: https://github.com/airbnb/lottie-web/issues/1561#issuecomment-482042277

### 6. PC ブラウザでプレビューを確認する
https://lottiefiles.com/preview に `JSON` 化したファイルをアップロードすると、プレビューを見ることができます。

![animation_pc_preview.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/186009/96610181-b03f-1263-dc10-c16418eb04da.png)

プレビューを見てアニメーションが正常にレンダリングされることを確認できたら次に進みます。（Lottieではまだ対応できていない Effect などがあるので正常にレンダリングされない場合があります）

参考: [AirbnbのアニメーションライブラリLottie(ロッティー)の使い方🎅](https://qiita.com/17genai/items/37e988d0f68ffe6b44ef#%E3%81%BE%E3%81%A0%E3%82%B5%E3%83%9D%E3%83%BC%E3%83%88%E3%81%95%E3%82%8C%E3%81%A6%E3%81%84%E3%81%AA%E3%81%84%E8%A1%A8%E7%8F%BE%E3%81%8C%E3%81%82%E3%82%8B)

### 7. Lottie のモバイルアプリでプレビューを確認する
`Lottie` にはモバイルアプリがあります。前のステップで確認したプレビューには QR コードがあるので、それをモバイルアプリでスキャンします。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/186009/2fd23202-d9ac-e8bc-8332-39c2968dc159.jpeg" width=200px>

`Android` と `iOS` の両端末で、アニメーションが正常に表示されることが確認できれば、アニメーション側の準備は完了です。

## React Native 側の準備
`package.json` にバージョンを指定した `lottie-react-native` を追記し、インストールする。

```package.json
{
  ...
  "dependencies": {
    ...
    "lottie-react-native": "^2.5.11"
    ...
  }
}
```

```console
npm i
```

※ `React Native` のバージョンが 0.59 よりも前だったので、 `lottie-react-native` のバージョンを指定しています。

参考: https://github.com/react-native-community/lottie-react-native#getting-started

### iOS
#### 1. Getting Started に従う
[Getting Started](https://github.com/react-native-community/lottie-react-native#getting-started) に従って、以下のコマンドを実行しました。

```console
react-native link lottie-ios
react-native link lottie-react-native
```

#### 2. アプリをビルドする
`iOS` 端末でビルドを実行し、アプリが正常に起動することを確認しました。

**注意**

以下のようなエラーが発生することがあるようです。

```console
error: /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator11.3.sdk/System/Library/Frameworks/Lottie.framework: No such file or directory
```

その際は、 `README` にしたがって `Xcode` の `Embedded Binaries` に `Lottie.framework` を追加することで解決するようです。

参考: https://github.com/react-native-community/lottie-react-native/issues/177#issuecomment-327677921

### Android
#### 1. Getting Started に従う
[Getting Started](https://github.com/react-native-community/lottie-react-native#getting-started) に従って、以下のコマンドを実行しました。

```console
react-native link lottie-react-native
```

#### 2. アプリをビルドする
`Android` 端末でビルドを実行したときに、以下の Warning が表示されました。

```console
Configuration 'compile' is obsolete and has been replaced with 'implementation' and 'api'.
It will be removed at the end of 2018. For more information see: http://d.android.com/r/tools/update-dependency-configurations.html
```

よって、以下の修正を行いました。

```diff:android/app/build.gradle
  dependencies {
-     compile project(':lottie-react-native')
+     implementation project(':lottie-react-native')
  }
```

参考: https://qiita.com/winningefa/items/9607c98c6ce7389c0520

また、私の場合ビルドが失敗しました。調査したところ、以下のコードを追加したことでビルドが成功しました。

````android/app/build.gradle
android {
    ...
    compileOptions {
        sourceCompatibility 1.8
        targetCompatibility 1.8
    }
    ...
}
```

参考: https://github.com/react-native-community/lottie-react-native/issues/434#issuecomment-461390167

## アニメーションの組み込み実装
[Getting Started](https://github.com/react-native-community/lottie-react-native#usage) にもあるように、以下のコードを組み込むとアニメーションが実際に表示されました。

```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 />;
  }
}
```


## 参考サイト一覧
- [Lottie 公式ドキュメント](http://airbnb.io/lottie/)
- [Lottie プレビューページ](https://lottiefiles.com/preview)
- [AirbnbのアニメーションライブラリLottie(ロッティー)の使い方🎅](https://qiita.com/17genai/items/37e988d0f68ffe6b44ef)
- [Android Studioの新コンフィグレーションimplementationとapiのひとつ注意点](https://qiita.com/winningefa/items/9607c98c6ce7389c0520)
- [lottie-react-native GitHub](https://github.com/react-native-community/lottie-react-native)
- https://github.com/airbnb/lottie-web/issues/1561
- https://github.com/airbnb/lottie-android/issues/1177
- https://github.com/react-native-community/lottie-react-native/issues/177
- https://github.com/react-native-community/lottie-react-native/issues/434