はじめに
ジョブカン事業部のアドベントカレンダー10日目の記事です
9日目の記事は @Larvesta636 さんによる「日報作成&工数出力のGUIアプリつくってみた」でした。執筆おつかれさまでした。
開発したツールで月次業務が軽減されると良いですね!
概要
本稿はAdobe AfterEffects(以下、AfterEffects)で作成したアニメーションをBodymovinとLottieを使用して、ブラウザー上で再生可能なSVGアニメーションとしてHTMLに埋め込むまでを実施してみます。
モチベーション
Webページにアニメーションを追加するとUX向上を期待できます。しかし、GIFアニメやMP4などの動画ファイルではファイルサイズが大きくなり、読み込み速度に影響を与えかねません。また、これらの形式はラスター形式であるため拡大するとジャギー(ギザギザ)が目立ちます。
SVGアニメーションなら軽量でギザギザしないスケーラブルなアニメーションを実現できます。が、凝ったアニメーションは実装に時間がかかり、実装しても正しく描画されないし変更が困難と感じるのはその辺りに触れたご経験があってもなくても共感いただけると思います。
そこで、今回はモーショングラフィックでお馴染みのAfterEffectsとそのプラグインを用いたSVGアニメーションを作ってみます。
それならFlash後継のAnimateでいいじゃないか
とお叱りを受けそうですが、あちらは正直なところ雲行きが怪しい(本体の開発が鈍化、出力が参照するライブラリーが古め)ので、見なかったことにしました。
Lottieなんて聞いたことがない。無名で実績のないライブラリーは怖くて使えない
とも言われそうですが、以下の公式概要ページを見るとAppleやGoogleなど誰もが知っている大手で使用実績があります。
執筆時現在のAppleはWebページ内の動画にMP4を使用していますが、iOS 18のページを開発者ツールで確認すると lottie
の文字列を見つけることができます。
じゃあMP4やめて全部Lottieにするわ
Bodymovinは万能ではありません
Bodymovinはサポートしていないアニメーション表現を無視して出力します。特にエフェクトはほとんど使用できないため、使用を諦めるか代替手段で実装する必要があります
例えば動画でよく使われるパーティクル(粒子表現)や複雑な3D表現は(執筆時現在では)できません。サポート状況は以下の公式ページに記載がありますが、設定画面とにらめっこしながら実際に出力してみるのがわかりやすいと思います
できたもの
- 約2秒のアニメーションです
- 中央あたりをクリック(タップ)するとアニメーションを再生します
- 再生中にクリックすると一時停止します
- 最後まで再生した状態でクリックすると最初から再生します
- 表示を拡大・縮小してもジャギらないことが実際に確認できると思います
See the Pen LGTM animation example by djwq (@djwq) on CodePen.
前提条件・環境構築
必要なツール・ライブラリ
-
AfterEffects
- 言わずと知れた動画作成ソフト。有償です
-
Bodymovin拡張機能
- AfterEffectsの動画をJSONとして出力します
-
Lottie Webライブラリ
- アニメーションが記述されたJSONを制御します
-
Webブラウザー
- 説明不要。モダンブラウザーならデスクトップでもスマートフォンでも可です
環境構築手順
- AfterEffects をインストール
- Bodymovin拡張機能をインストール
-
Adobe ExchangeやLottieのGitHubページからもDL可能ですが、aescripts + aeplugins(AfterEffects拡張機能のストアサイト)からのDLを公式では推奨しているようです
- 金額が
$20.00
になっていますが、自分で指定できるので$0.00
も可能です - manager appがあるとインストールが楽です。おすすめです
- 金額が
-
Adobe ExchangeやLottieのGitHubページからもDL可能ですが、aescripts + aeplugins(AfterEffects拡張機能のストアサイト)からのDLを公式では推奨しているようです
なお、実行はWebブラウザーで完結するのでNode.jsなどのJavaScript環境は不要です。
実装方法
AfterEffectsでアニメーションを作成
Lottieを使う前にまずアニメーション本体を作成します。
詳細な作り方を省いても長くなったので折りたたみました
- 新しいコンポジションを作成してサイズとフレームレートを設定します
- とりあえず400px*400px, 60fpsにしました
-
LGTM
を配置します。文字は独立してアニメーションさせるので、単一のテキストレイヤーではなくバラバラに配置します- フォントはQuicksand Boldにしました。いい感じにころんとしていてかわいいです
- 余談ですが実はGoogle Fontsの一部です。知らなかった...
- フォントはQuicksand Boldにしました。いい感じにころんとしていてかわいいです
- 4つのテキストレイヤーそれぞれからシェイプレイヤーを作成します
- テキストレイヤーのままではユーザー環境にフォントを要求するため、未インストールの環境では何も表示されません(n敗)
- これを回避するため、テキストデータをベクターデータに変換して図形として扱うようにします
- アニメーションを設定していきます。この作例は色の変化を除くと
トランスフォーム
で完結します- L ...
位置
と回転
をアニメーションします - G ...
回転
を設定しておき位置
をアニメーションします。落下時は縦長、衝突時に横長になるようスケール
を適度に設定します。アニメーション後半で回転
を戻します
←落下時 地面衝突時→ - T ...
アンカーポイント
を中央下に設定しておきスケール
をアニメーションします。スケールが最高地点になったら位置
もアニメーションさせます - M ... 3Dレイヤーを設定しておき、
Y回転
をアニメーションします。90°を設定してもきれいに隠れないので、回転がはじまるまでは不透明度
を0%
にしています - 後半でシェイプの
塗り
を#62A365
に設定します - 基本的にキーフレームにはイージーイーズを設定しておきます
- 必要に応じてグラフエディターで速度調整して動きに緩急をつけます
- 感覚ですが、速→遅にしておくといい感じになります
- タイムラインは以下のようになりました。
スケール
をアニメーションしているヌルオブジェクトは、シェイプレイヤーに設定すれば不必要かもしれません
- L ...
BodymovinでJSONファイルをエクスポート
AfterEffectsでアニメーションを作ったら、次にJSONファイルへエクスポートします。
-
AfterEffectsのメニューから
ウィンドウ
>エクステンション
>Bodymovin
を選択します -
出力フォルダを指定します
-
Render
ボタンをクリックして、JSONファイルを出力します
出力フォルダの設定を行いましたか?
手順3も必須です。筆者はこれを忘れてRender
ボタンが押せず、小一時間溶かしました
出力が成功すると以下のような表示になります
HTMLにアニメーションを組み込む
JSONファイルにエクスポートしたら、コードを書いて実際にアニメーションさせます。
完成形のコードを見たい
コード全文は上記サンプルのHTML
, CSS
, JS
タブより参照いただけます
HTML
Lottieライブラリの読み込みます。
手っ取り早く確認するにはCDNのJSを読み込むのが良いと思います
<script src="https://cdnjs.cloudflare.com/ajax/libs/lottie-web/5.12.2/lottie.min.js"></script>
アニメーションを描画する要素を用意します。
サイズはCSSで指定するので、ここでは要素の配置のみとします。JavaScriptから要素を参照するのでid
属性を正しく設定しておくとよいかなと思います
<div id="lottie"></div>
CSS
描画する要素のサイズを指定します。
スケーラブルなのでいくつでもよいですが、とりあえずコンポジションと同じく400px*400pxにします。ついでに見た目をよくするためmargin
でセンタリングします
div#lottie {
width: 400px;
height: 400px;
margin: 0 auto;
}
JavaScript
Bodymovinが出力したJSONを記述します。
ファイルからロードできればそれもよいですが、外部サーバーを用意するのは面倒なので愚直にdata.json
を展開します
const data = {...}; // data.jsonの中身
続いて初期化をします。アニメーションを描画する要素の決定とアニメーションの読み込みを行います。
特に設定していないと自動再生するので autoplay: false
を設定します。さらにloop: false
を設定してループ再生は無効にします(画面がうるさくなるので)
// 描画要素を取得
const lottieContainer = document.querySelector("#lottie");
// アニメーション初期化
const animation = lottie.loadAnimation({
container: lottieContainer, // 描画する要素
animationData: data, // エクスポートしたJSON
autoplay: false, // 自動再生
loop: false // ループ再生
});
描画する要素とアニメーションにコールバック関数を設定します。アニメーションが再生中かの情報は取得できないようなので自前で管理します
// 再生中?
let playing = false;
// 再生完了?
let completed = false;
// 描画要素のクリックイベント
lottieContainer.onclick = () => {
if (playing) {
// 再生中なら一時停止
playing = false;
animation.pause();
} else {
if (completed) {
// 再生終了済みなら先頭に戻す
animation.goToAndStop(0);
completed = false;
}
// 再生
playing = true;
animation.play();
}
};
// アニメーション完了イベント
animation.onComplete = () => {
playing = false;
completed = true;
};
これでCodePenのサンプルと同じ動作をするはずです
もう少し実用的な例
文字をアニメーションさせるだけでは実用的な使い方のイメージがしにくいかなと思ったので、無限スクロールで使えそうなアニメーションを作ってみました
- 画面中央部をクリックするとアニメーションします
- さらにクリックすると状態遷移します(待機中→処理中→完了→待機中→...)
- 実際にロードするものがないので、代わりにクリックで擬似的に状態遷移しています
See the Pen Loading Sample by djwq (@djwq) on CodePen.
まとめ
本稿では、AfterEffectsで作成したアニメーションをBodymovinとLottieを使用してWebページに埋め込む方法を解説しました。今回はWebページでしたが、LottieはiOSやReact(非公式)など様々な環境で動作するよう移植されています。
また、Lottieは逆再生やスクロール位置に応じたアニメーションなど、本稿では紹介していない機能もあります。ぜひご自身のプロジェクトで活用してみてください。
試してみたいけどAfterEffectsなんて持っていない!という各位は以下のページにあるファイルでLottieを試すことができます(要登録)
さいごに
DONUTSでは一緒に働くメンバーを募集しています。
昨年や今年のアドベントカレンダーをご覧になっておもしろそうな人がいる、自分ならプロダクトをもっとよくできるなどジョインしたいという想いがありましたら、以下のページをご覧ください。お待ちしております。
明日の記事は @imadon2024 さんによる「NetflixのSystem Designを眺めてみた」です。ここまで読んでいただいた各位はNetflixのアーキテクチャーも是非眺めてみてください。
記事は以上です。アドカレ初投稿の鳩(@djwq)でした。