これは何
以下の流れをまとめた記事です。
- After Effectsで作ったアニメーションを
- Lottie(Bodymovin)でJSONに書き出して
- React上で
onClick
で動くようにする
完成物そのものは、button
をクリックするとアニメーションがスタートするだけのシンプルなものです。
また、GitHub Pagesで実際に触れるようにしつつ、
コードも全て公開しています。
なお、この記事ではアニメーションの作り方自体の説明はしません。
以前私が書いた記事で初歩の初歩だけ紹介しているので、興味のある方はこちらをどうぞ。
全体の流れ
- Lottieの紹介
- After EffectsにBodymovinをインストールする(初回のみ)
- After EffectsからJSONを書き出す
- Reactのプロジェクト上で
react-lottie
を用いる - 余談:サンプルコードの通りだと上手く動かない箇所
import * as animationData from './path/to/json'
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
の登場です。
インストール
$ npm i react-lottie
# or
$ yarn add react-lottie
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
import Lottie from 'react-lottie';
import animationData from './animation.json';
react-lottie
と、書き出して配置したJSONをimportします。
options
const defaultOptions = {
loop: false,
autoplay: false,
animationData,
rendererSettings: {
preserveAspectRatio: 'xMidYMid slice'
}
};
例ではこのように書きましたが、最小ならこうです。
const defaultOptions = { animationData };
JSONさえ読めていれば、ループや自動再生は初期値(両方true)として動いてくれます。
TypeScriptを使う使わないに関わらず、型定義ファイルを見れば分かりやすいでしょう。
Lottie component
<Lottie
options={defaultOptions}
height='50vmin'
width='50vmin'
isStopped={stop}
isClickToPauseDisabled={true}
ariaRole=''
eventListeners={[
{
eventName: 'complete',
callback: () => setStop(true),
},
]}
/>
今回自分がオプションを設定した意図は以下のものです。
- SVG要素自体はクリックできないようにしたい
- 別なbutton要素をクリックすることで再生をスタートしたい
- buttonをクリックするたびアニメーションが再生してほしい
デフォルトだとアニメーションするSVG要素自体がクリックでき、かつrole
にbutton
があたっているのでisClickToPauseDisabled
とariaRole
を設定したのと、complete
イベントの発火(=アニメーション再生終了)時にアニメーションをリセットするためにstateを操作しています。
Lottieではstop
は最初のフレームに戻りつつ動作停止。
対してpause
は一時停止と明確に役割が分かれています。
そのため、アニメーションが終了したらstop
を指定することで何度も再生できるようにしています。
このあたりは自分の作りたいアニメーションを想定しつつドキュメントとにらめっこ、実際に動かしながら確認するしかないかもしれません。
余談:サンプルコードの通りだと上手く動かない箇所
見出しの通りで、サンプルをコピペしたら動かなかった箇所がありました。
対処法含めてここに載せておきます。
import * as animationData from './path/to/json'
import * as animationData
をimport animationData
にすれば解決しました。
また、それにあわせてoptions
のanimationData: animationData
もanimationData
だけに省略できます。
1つのファイルで1つのアニメーションしか使わないなら、この方が短く書けますね。
こちらのIssueで話されていました。
setupTests.js
jest-canvas-mock
をインストールしていない状態でテストを走らせるとコケてしまうみたいです。
$ npm i --save-dev jest-canvas-mock
# or
$ yarn add -D jest-canvas-mock
インストールした上で
import '@testing-library/jest-dom';
+ import 'jest-canvas-mock';
setupTests.js
でimportすればなおりました。
まとめ
- After EffectsにBodymovinをインストールする
- After Effectsでアニメーションを作成する
- シェイプレイヤーかパスデータだけで作る
- 複雑なマスクを使わない
- 基本、エフェクトは使えないものと考える
- BodymovinでJSONに書き出す
-
react-lottie
をインストールして、書き出したJSONを読み込んでLottie
コンポーネントを配置する - 各種オプションを調整する
-
例なので非常に簡単なもので完成としていますが実際はここで作り込みます。 ↩