After Effectsで作ったアニメーションをreact-lottieで実装する


これは何

以下の流れをまとめた記事です。

  • After Effectsで作ったアニメーションを
  • Lottie(Bodymovin)でJSONに書き出して
  • React上でonClickで動くようにする

完成物そのものは、buttonをクリックするとアニメーションがスタートするだけのシンプルなものです。

また、GitHub Pagesで実際に触れるようにしつつ、

コードも全て公開しています。

なお、この記事ではアニメーションの作り方自体の説明はしません。
以前私が書いた記事で初歩の初歩だけ紹介しているので、興味のある方はこちらをどうぞ。

全体の流れ

  1. Lottieの紹介
  2. After EffectsにBodymovinをインストールする(初回のみ)
  3. After EffectsからJSONを書き出す
  4. Reactのプロジェクト上でreact-lottieを用いる
  5. 余談:サンプルコードの通りだと上手く動かない箇所
    1. import * as animationData from './path/to/json'
    2. setupTests.js

Lottieの紹介

Lottieについて、公式のドキュメントより説明を引用します。

Lottie is a library for Android, iOS, Web, and Windows that parses Adobe After Effects animations exported as json with Bodymovin and renders them natively on mobile and on the web!

今回はWebでの話、特にReactアプリケーションでLottieを使う際の話です。

Webで動画を扱うにあたって、一番ネックになるのはファイルの容量の大きさではないでしょうか。
綺麗な動画を届けようとすればするほど重くなり、ユーザー体験を損ねかねません。

ですが、Lottieを使うとJSONを読み込むだけでアニメーションを実装できます。
実際に画面に描画されるのもsvg要素なので、かなり軽く済むんですね。

After EffectsにBodymovinをインストールする(初回のみ)

After Effectsで作成したアニメーションを、Lottieで扱えるJSONに変換してくれるのがBodymovinです。
導入の仕方は何パターンかありますが、自分はAdobe Exchangeからインストールしました。

アクセスして、画面の右上あたりにあるFreeボタンを押せばCreative Cloudアプリが立ち上がってインストールが始まると思います。

ちゃんとインストールできていれば、ウィンドウ > エクステンションの中にBodymovinの項目が出現しているはずです。

After EffectsからJSONを書き出す

アニメーション作成についての説明は飛ばして、書き出し方を説明します。

上記のように、無限にループする円のアニメーションを作成しました。1

次にウィンドウ > エクステンション > Bodymovinを起動。

このようなウィンドウが開くはずです。
更にSettingsを選びましょう。

設定項目の詳細は公式ドキュメントのComposition Settingsの章を読んでいただく方が良いかと思いますが、いつも私がチェックを入れるのは以下の3つです。

  • Glyphs
    • 今回は使っていませんが、テキストを使っている際は必須
    • いわゆるアウトライン化をしてくれるオプション
  • Standard
    • 実装する際のJSONを書き出してくれるためオプションのため必須
  • Demo
    • ローカルで開くだけで動きを確認できるHTMLを吐いてくれる
    • 実際に近い確認ができるのでいつも一緒に書き出している

設定を確認したらSaveを押し、ひとつ前の画面に戻ります。
/Users/..と書いてある箇所をクリックすると保存場所とファイル名を選べるので、設定してRenderを押しましょう。

データや設定に問題がなければRender finishedと画面に表示されるはずです。

ひとつ注意が必要なのが、BodymovinはAfter Effectsの全ての機能に対応しているわけではないこと……。

詳しくは上記のページにまとまっていますが、以下の項目に気をつけていればよっぽど大丈夫だと思います。

  • シェイプレイヤーかパスデータだけで作る
  • 複雑なマスクを使わない
  • 基本、エフェクトは使えないものと考える

Reactのプロジェクト上でreact-lottieを用いる

ここからは実際のReactアプリケーション上でアニメーションを動かす流れを説明します。
今回は例なので、Create React Appで生成されるページをそのまま使いますがご了承ください。

まずは先ほど書き出したファイルを適当なディレクトリに格納。
自分はsrc直下にanimation.jsonという名前で置きました。

そしてやっとreact-lottieの登場です。

インストール

react-lottieのインストール
$ npm i react-lottie

# or

$ yarn add react-lottie

App.jsの編集

App.js
import { useState } from 'react';
import './App.css';
import Lottie from 'react-lottie';
import animationData from './animation.json';

function App() {
  const [stop, setStop] = useState(true);

  const defaultOptions = {
    loop: false,
    autoplay: false,
    animationData,
    rendererSettings: {
      preserveAspectRatio: 'xMidYMid slice'
    }
  };

  return (
    <div className="App">
      <header className="App-header">
        <Lottie
          options={defaultOptions}
          height={'50vmin'}
          width={'50vmin'}
          isStopped={stop}
          isClickToPauseDisabled={true}
          ariaRole={''}
          eventListeners={[
            {
              eventName: 'complete',
              callback: () => setStop(true),
            },
          ]}
        />
        <button onClick={() => setStop(false)} className='App-button' disabled={!stop}>Start</button>
      </header>
    </div>
  );
}

export default App;

いきなり完成形を出してしまいましたが、順に解説します。

import

App.js
import Lottie from 'react-lottie';
import animationData from './animation.json';

react-lottieと、書き出して配置したJSONをimportします。

options

App.js
const defaultOptions = {
  loop: false,
  autoplay: false,
  animationData,
  rendererSettings: {
    preserveAspectRatio: 'xMidYMid slice'
  }
};

例ではこのように書きましたが、最小ならこうです。

App.js
const defaultOptions = { animationData };

JSONさえ読めていれば、ループや自動再生は初期値(両方true)として動いてくれます。
TypeScriptを使う使わないに関わらず、型定義ファイルを見れば分かりやすいでしょう。

Lottie component

App.js
<Lottie
  options={defaultOptions}
  height='50vmin'
  width='50vmin'
  isStopped={stop}
  isClickToPauseDisabled={true}
  ariaRole=''
  eventListeners={[
    {
      eventName: 'complete',
      callback: () => setStop(true),
    },
  ]}
/>

今回自分がオプションを設定した意図は以下のものです。

  • SVG要素自体はクリックできないようにしたい
  • 別なbutton要素をクリックすることで再生をスタートしたい
  • buttonをクリックするたびアニメーションが再生してほしい

デフォルトだとアニメーションするSVG要素自体がクリックでき、かつrolebuttonがあたっているのでisClickToPauseDisabledariaRoleを設定したのと、completeイベントの発火(=アニメーション再生終了)時にアニメーションをリセットするためにstateを操作しています。

Lottieではstopは最初のフレームに戻りつつ動作停止。
対してpauseは一時停止と明確に役割が分かれています。

そのため、アニメーションが終了したらstopを指定することで何度も再生できるようにしています。
このあたりは自分の作りたいアニメーションを想定しつつドキュメントとにらめっこ、実際に動かしながら確認するしかないかもしれません。

余談:サンプルコードの通りだと上手く動かない箇所

見出しの通りで、サンプルをコピペしたら動かなかった箇所がありました。
対処法含めてここに載せておきます。

import * as animationData from './path/to/json'

import * as animationDataimport animationDataにすれば解決しました。
また、それにあわせてoptionsanimationData: animationDataanimationDataだけに省略できます。
1つのファイルで1つのアニメーションしか使わないなら、この方が短く書けますね。

こちらのIssueで話されていました。

setupTests.js

jest-canvas-mockをインストールしていない状態でテストを走らせるとコケてしまうみたいです。

jest-canvas-mockのインストール
$ npm i --save-dev jest-canvas-mock

# or

$ yarn add -D jest-canvas-mock

インストールした上で

setupTests.js
  import '@testing-library/jest-dom';
+ import 'jest-canvas-mock';

setupTests.jsでimportすればなおりました。

まとめ

  1. After EffectsにBodymovinをインストールする
  2. After Effectsでアニメーションを作成する
    1. シェイプレイヤーかパスデータだけで作る
    2. 複雑なマスクを使わない
    3. 基本、エフェクトは使えないものと考える
  3. BodymovinでJSONに書き出す
  4. react-lottieをインストールして、書き出したJSONを読み込んでLottieコンポーネントを配置する
  5. 各種オプションを調整する

  1. 例なので非常に簡単なもので完成としていますが実際はここで作り込みます。