Webサイトにおけるアニメーション実装へのアプローチ 〜未だ見果てぬ夢〜

私は常々 Web サイトにおいてアニメーションはなくてもよい存在だと考えています。なぜならば・・・と話を続けたくはあるのですが、まあ正当な強い持論があるわけでもないので、ここで大仰に語ることは控えておきます。アニメーションを実装する立場でありながら、そのような考えをもち常に自責の念にかられながらも制作を続けています。そんな中でさまざまな実装へのアプローチを試みた雑な感想を、簡単なデモとあわせてご覧ください。

# 1. JavaScript で要素を動かす
古から伝えられてきた魔法。緻密な計算を駆使してあらゆるものを自在に操れ。
<p data-height="400" data-theme-id="0" data-slug-hash="XyBJdB" data-default-tab="js,result" data-user="syuji-higa" data-pen-title="Animation vanilla" class="codepen">See the Pen <a href="https://codepen.io/syuji-higa/pen/XyBJdB/">Animation vanilla</a> by Syuji Higa (<a href="https://codepen.io/syuji-higa">@syuji-higa</a>) on <a href="https://codepen.io">CodePen</a>.</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

言わずもがな、ブラウザで動くスクリプトです。トランスパイラやらコンパイラやらは溢れてはいますが、結局はこの言語になります。前までは要素を動かす選択肢はこれだけでした。`marquee` なんてものもありましたけど。正直、アニメーションさせるのはそこそこ大変です。

<p data-height="400" data-theme-id="0" data-slug-hash="rQraBd" data-default-tab="js,result" data-user="syuji-higa" data-pen-title="Animation anime.js" class="codepen">See the Pen <a href="https://codepen.io/syuji-higa/pen/rQraBd/">Animation anime.js</a> by Syuji Higa (<a href="https://codepen.io/syuji-higa">@syuji-higa</a>) on <a href="https://codepen.io">CodePen</a>.</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

その大変さゆえ、多くのさまざまなライブラリが誕生しました。それだけ世の中でアニメーションが求められたということでしょう。今回は [anime.js](http://animejs.com/) を選びましたが理由は特になし。コードを見ると一目瞭然ですが、ライブラリをつかわない時とくらべるとだいぶ短くなっていますね。

以降の実装のほとんどに何らかの形で関わることが多い JavaScript。逆にいえば大抵のことはできてしまうのです。大変ですが。とはいえ、ライブラリを使えば楽になりますし、これといった大きな問題はないかと思います。しいていうのであれば、ライブラリに依存する点と、その分のファイルサイズが増えるといったところでしょうか。

ライブラリを使わず書くこともあるのですが、アニメーションを理解する上ではとても有意義なことであり、それが原点であることをこと考えると私は震えずにはいらないのです。

# 2. CSS で要素を動かす
いつもそばにいるよ。マルチスキルをつかいこなせ。
<p data-height="400" data-theme-id="0" data-slug-hash="QJBWed" data-default-tab="css,result" data-user="syuji-higa" data-pen-title="Animation css (add class)" class="codepen">See the Pen <a href="https://codepen.io/syuji-higa/pen/QJBWed/">Animation css (add class)</a> by Syuji Higa (<a href="https://codepen.io/syuji-higa">@syuji-higa</a>) on <a href="https://codepen.io">CodePen</a>.</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

プロパティとして `transition` と `animation` が用意されています。手軽に実装できますし、トリガーが必要な場合でも JavaScript からクラスを追加で発火させることができます。JavaScript 内に書くと煩雑になりがちなロジックを分離できるのは魅力的ですね。`pointer-events` をつかうと全画面表示のメニューなどもアニメーションさせることができます。そして、一部のプロパティは GPU で処理することができるのは素晴らしいです。

ただし、動的な数値を与えることは難しく、シーケンスのあるような複雑な動きには弱くなりがちです。

昨今はやりのフレームワークとの相性の良さなどを考えると、この手法はしばらくは続きそうです。今では当たり前になっていますが、CSS アニメーションが登場したときの希望の灯火は、とてもあたたかくてやさしいものだったと記憶しています。

<p data-height="400" data-theme-id="0" data-slug-hash="XyBJXB" data-default-tab="css,result" data-user="syuji-higa" data-pen-title="Animation css (control JavaScript)" class="codepen">See the Pen <a href="https://codepen.io/syuji-higa/pen/XyBJXB/">Animation css (control JavaScript)</a> by Syuji Higa (<a href="https://codepen.io/syuji-higa">@syuji-higa</a>) on <a href="https://codepen.io">CodePen</a>.</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

これは結果として微妙だったのですが、CSS に記述した `keyframes` を JavaScript から操作する試みのデモです。

何故に試したのかというと、JavaScript から操作しやすい状態にしつつアニメーションのロジックを省き、かつ CSS もスッキリさせようと考えたからです。まあ、結果は JavaScript 側の記述もソコソコあり半端なかたちになりました。ダメという程ではないのですが、わざわざこの方法をとることはないかと思います。

それでも、チャレンジしたことには後悔はしていないし、むしろとても楽しい時間を提供しくれてありがとう。と私はいいたいのです。

# 3. Web Animations API で要素を動かす
いまだ未来の技術。タイムマシンで時代を先取り。
<p data-height="400" data-theme-id="0" data-slug-hash="KrBwMX" data-default-tab="js,result" data-user="syuji-higa" data-pen-title="Animation Web Animations API" class="codepen">See the Pen <a href="https://codepen.io/syuji-higa/pen/KrBwMX/">Animation Web Animations API</a> by Syuji Higa (<a href="https://codepen.io/syuji-higa">@syuji-higa</a>) on <a href="https://codepen.io">CodePen</a>.</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

まだ[草案](https://developer.mozilla.org/ja/docs/Web/API/Web_Animations_API#Specifications)ですし、ブラウザの対応もまだまだですが、Polyfill の [web-animations-js](https://github.com/web-animations/web-animations-js) で大抵の機能はつかうことができます。まるで JavaScript で CSS の `animation` を扱うかのようです。実際そうなのかもですが。ちなみに、デベロッパーツールでも CSS アニメーションと同じようにデバッグできます。あと SVG にも対応しているのは最高ですね。

みんな大好き Promise を返して欲しければ[ビルドターゲット](https://github.com/web-animations/web-animations-js/blob/dev/docs/experimental.md#build-target-comparison)を切り替えて web-animations-next か web-animations-next-lite をつかうとよいです。

ひとつ、`fill: 'forwards'` には気をつけましょう。CSS からスタイルの上書きができないからです。[`cancel()`](https://developer.mozilla.org/ja/docs/Web/API/Animation/cancel) を実行すると上書きできるようになるのですが、初期値にもどってしまうので対応が必要になります。（「[ダメな場合](https://codepen.io/syuji-higa/pen/eQjJrP)」と「[対応した場合](https://codepen.io/syuji-higa/pen/XyBXww)」の例。アニメーション後にホバーが効くか確認してみてください）

総評としてはライブラリと同等程度の機能はあると感じましたし、基本的にはつかいやすいです。それ故に上記の問題は悲しいものです。あと、 Polyfill 入れるのであれば、ライブラリ入れればいいじゃない感が否めないところはあります。

手放しでオススメできるわけではないのですが、未来は眩しすぎるほどに輝いていると私は信じてやまないのです。


# 4. GIF アニメーションを再生する
古き良き相棒。みんなを楽しませつづける Web 界のピエロ。
<p data-height="400" data-theme-id="0" data-slug-hash="KrEMmy" data-default-tab="html,result" data-user="syuji-higa" data-pen-title="Animation AniGif" class="codepen">See the Pen <a href="https://codepen.io/syuji-higa/pen/KrEMmy/">Animation AniGif</a> by Syuji Higa (<a href="https://codepen.io/syuji-higa">@syuji-higa</a>) on <a href="https://codepen.io">CodePen</a>.</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

Web の黎明期からつかわれつづけてきたメディアですね。時代は変わり続けてて、紆余曲折ありながらも未だに現役。つかいどころは選ぶものの、ここぞというタイミングには出番があります。

透過する場合は GIF 同様にジャギーの問題があります。また、再生速度やコマ数の数によってパフォーマンスが左右されますので、大量に描画する際などは確認が必要です。あとは、基本的に再生タイミングの制御ができません。まあ、できないことも無いですが。

いつの時代でも、その手軽さや GIF アニメらしさは人々を魅了してやまない存在です。

# 5. APNG を再生する
超進化。未だ争い続けるもの。
<p data-height="400" data-theme-id="0" data-slug-hash="XyGePe" data-default-tab="html,result" data-user="syuji-higa" data-pen-title="Animation APNG" class="codepen">See the Pen <a href="https://codepen.io/syuji-higa/pen/XyGePe/">Animation APNG</a> by Syuji Higa (<a href="https://codepen.io/syuji-higa">@syuji-higa</a>) on <a href="https://codepen.io">CodePen</a>.</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

我らが救世主 PNG が APNG となって、また助けてくれるのでしょうか？形式としては、8bit と 32bit があります。32bit の場合はフルカラーでアルファチャンネルがつかえます。これはとても嬉しいいですね。ジャギーともおさらばです。

対応していないブラウザもありますが、その場合は静止画が表示されます。僕的にはそれで十分だと思っていますが、代わりに `canvas` で表示する [apng-canvas.js](https://github.com/davidmz/apng-canvas) もあります。

32bit のときは GIF アニメーションよりファイルサイズが増えますので、状況によっては 8 bit にするとよいでしょう。

WebP と争い続けてきましたが、現在は APNG が一歩優勢ですかね。これからの選択肢のひとつになるのではないでしょうか。

# 6. スプライトアニメーションでパラパラ
古典的な手法。アニメーションはここから始まった。
<p data-height="400" data-theme-id="0" data-slug-hash="xQBPwy" data-default-tab="css,result" data-user="syuji-higa" data-pen-title="Animation SpriteAnimation" class="codepen">See the Pen <a href="https://codepen.io/syuji-higa/pen/xQBPwy/">Animation SpriteAnimation</a> by Syuji Higa (<a href="https://codepen.io/syuji-higa">@syuji-higa</a>) on <a href="https://codepen.io">CodePen</a>.</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

これはアニメーションの原点であり、結局は動画だろうと Gif アニメーションだろうと、すべてのアニメーションはパラパラ漫画です。それをローレベルに実装したものと考えるとよいですかね。デモはスプライトシートをつかった CSS アニメーションで実装しまたが、方法はいろいろとあります。容量や制御、コストなどのバランスがよいので、なんだかんだでつかう機会はあるかと思います。

コマ数が多すぎると画像ファイルが重くなるので、その場合は別の手法に変えたほうがよいかもです。あと、レスポンシブにすると 1px 以下の微妙なズレがおきてしまいますので、`canvas` で対応する必要があります。

誰しも一度はノートの端にパラパラ漫画を描いたことはあるでしょう。あれこそがクリエイター魂の生まれた瞬間だったのではないでしょうか。

# 7. 動画を再生する
唯一無二の存在。あらゆるものを表現しよう。
<p data-height="400" data-theme-id="0" data-slug-hash="eQXZqy" data-default-tab="html,result" data-user="syuji-higa" data-pen-title="eQXZqy" class="codepen">See the Pen <a href="https://codepen.io/syuji-higa/pen/eQXZqy/">eQXZqy</a> by Syuji Higa (<a href="https://codepen.io/syuji-higa">@syuji-higa</a>) on <a href="https://codepen.io">CodePen</a>.</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

アニメーションをつくって動画にする手法ですね。形式はさまざまなので省きますが、`video` タグで再生するのが一般的でしょう。ある意味で最強の手法で、インタラクションを含まないアニメーションであれば大抵のことは表現できます。そして、音を含めることができるのはとても魅力的です。

問題点は、ダウンロード時間や通信量の増加、画質の調整などが考えられます。特にスマホなどで考慮する必要があり、なおかつ、音声つきの動画の再生にはユーザのアクションが必要とされます。

外部の動画サービスにアップロードして API を利用して再生する方法もよくありますね。ただし、Web サイトのアニメーションのひとつして取り込むのはイロイロと問題がでてきそうな気はします。

小難しいところはありますが、僕が生きている間はなにかと頼りつづけることになるのではないかと思います。

# 8. SVG を SMIL で動かす
集まれ。その全ては彼の中で。
<p data-height="400" data-theme-id="0" data-slug-hash="NEOQWQ" data-default-tab="html,result" data-user="syuji-higa" data-pen-title="Animation SVG (SMIL)" class="codepen">See the Pen <a href="https://codepen.io/syuji-higa/pen/NEOQWQ/">Animation SVG (SMIL)</a> by Syuji Higa (<a  href="https://codepen.io/syuji-higa">@syuji-higa</a>) on <a href="https://codepen.io">CodePen</a>.</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

一言でいうと SVG 内に書ける実装です。そこで完結できることや、CSS と JavaScript からアニメーションのロジックを分離できているところは、とても面白いですね。

再生の制御にはやはり JavaScript はかかせないですし、対応していなブラウザもあります。Polyfill はチョットよく分かんないので誰か調べておいてください。

こういった普段見ないような仕様をみると、大変ではありますがワクワクしてきちゃいますね。

# 9. Lottie で再生する
新境地。このときアニメーションは旅立った。
<p data-height="400" data-theme-id="0" data-slug-hash="vQQOrG" data-default-tab="js,result" data-user="syuji-higa" data-pen-title="SVG lottie" class="codepen">See the Pen <a href="https://codepen.io/syuji-higa/pen/vQQOrG/">SVG lottie</a> by Syuji Higa (<a href="https://codepen.io/syuji-higa">@syuji-higa</a>) on <a href="https://codepen.io">CodePen</a>.</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

After Effects でアニメーションをつくり、出力した `json` をもとに、JavaScript で `svg` を生成・制御するという手法です。Web との相性がとてもよい実装だと思いました。JavaScript での制御も簡単です。それに `svg` というのはよいですね。

ただ、After Effects から上手く出力できないこともありますので、確認をしながらつくる必要はあります。

実際のプロジェクトでつかったことはないのですが、とても期待していて次のプロジェクトで試してみる予定です。きっと、僕も新たな扉を開くときがきたのでしょう。

# 10. Canvas で描く
それは白いキャンバス。思うがままに筆をはしらせろ。
<p data-height="400" data-theme-id="0" data-slug-hash="qQQOXa" data-default-tab="js,result" data-user="syuji-higa" data-pen-title="Animation Canvas" class="codepen">See the Pen <a href="https://codepen.io/syuji-higa/pen/qQQOXa/">Animation Canvas</a> by Syuji Higa (<a href="https://codepen.io/syuji-higa">@syuji-higa</a>) on <a href="https://codepen.io">CodePen</a>.</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

ひとつの要素の中でグラフを描いたり、写真を合成したり、とさまざまなものを表示することでができます。大体の Web ゲームはこれでできているかと思います。今までできなかった画像の色情報を扱えるようになったことは大きいですね。それに、いくつかライブラリがありますし、アプリで生成することもできます。また、後述する WebGL ではできないこともあります。

しかし、大きな領域を描画すると動作が重くなってしまうこともありますので、パフォーマンスには気をつけなくてはならないです。

はじめて存在を知ったとき、なんて素敵な名前なんだろうって思いました。今では名前同様に素敵なやつだと感じています。

# 11. WebGL で描く
GPU は友達だ。ハイパフォーマンスに酔いしれろ。
<p data-height="400" data-theme-id="0" data-slug-hash="VVRKXz" data-default-tab="js,result" data-user="syuji-higa" data-pen-title="Animation WebGL" class="codepen">See the Pen <a href="https://codepen.io/syuji-higa/pen/VVRKXz/">Animation WebGL</a> by Syuji Higa (<a href="https://codepen.io/syuji-higa">@syuji-higa</a>) on <a href="https://codepen.io">CodePen</a>.</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

要素としては Canvas なのですが、扱うコンテキストが違います。GPU で描画することでより多くの処理をおこなっても動きをなめらかにを保つことができます。難しくはありますが、つかいやすいライブラリもありますので心配することはないでしょう。また、3D をあつかうのに適している点も大きな魅力ですね。あと、最近の `canvas` でできた Web ゲームは、WebGL であることが多いかと思います。

Web サイト全体の処理が重くなりがちで、マシン自体にも負荷がかるので、つかいどころを考えることが必要です。ですので、パフォーマンチューニングもとても大切です。

ひとつ上の次元を自在にあやつることができる楽しさは、他には真似できないものだと思います。

<p data-height="400" data-theme-id="0" data-slug-hash="LXaLQw" data-default-tab="html,result" data-user="syuji-higa" data-pen-title="Animation WebGL (GLSL)" class="codepen">See the Pen <a href="https://codepen.io/syuji-higa/pen/LXaLQw/">Animation WebGL (GLSL)</a> by Syuji Higa (<a href="https://codepen.io/syuji-higa">@syuji-higa</a>) on <a href="https://codepen.io">CodePen</a>.</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

これは、アニメーションの核になる実装部分を GLSL（GPU）で対応したものです。JavaScript（CPU）側で対応するか、GLSL（GPU）側で対応するかの違いです。どちらが処理的に早いのかは場合によると思いますが、両方とも理解しておくとさまざまな状況に対応できます。

その他にも、複数の頂点データを用意してモーフィングさせることができます。この場合、基本的には JavaScript（CPU） 側での処理になります。

# 12. GLSL でシェーダアート
マシンよ唸れ。そこは無限の空間。
<p data-height="400" data-theme-id="0" data-slug-hash="xQBLVG" data-default-tab="html,result" data-user="syuji-higa" data-pen-title="Animation GLSL ShaderArt" class="codepen">See the Pen <a href="https://codepen.io/syuji-higa/pen/xQBLVG/">Animation GLSL ShaderArt</a> by Syuji Higa (<a href="https://codepen.io/syuji-higa">@syuji-higa</a>) on <a href="https://codepen.io">CodePen</a>.</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

これも WebGL ではあるのですが、主に四角形でつくられた板ポリをキャンバスとして、ひとつひとつのピクセルに色を入れることで描写します。ジェネラティブアートやクリエイティブコーディングと呼ばれるもののひとつです。数学的な計算をつかい世界を描こうとする姿は知的でかっこいいですね。

WebGL なので基本的にデメリットも同じです。ただし、必然的に描画領域すべてのピクセルを出力する必要があり、多大な描画コストがかかりがちです。ノイズなどの複雑な計算をすることで、急激に負荷が上がってしまいますので注意が必要です。

つかいどころは難しいですが、さまざまな計算から出力された世界にふれることで、数学の美しさに気づくことができるでしょう。

<p data-height="400" data-theme-id="0" data-slug-hash="zyOrQm" data-default-tab="html,result" data-user="syuji-higa" data-pen-title="Animation GLSL ShaderArt (Raymarching)" class="codepen">See the Pen <a href="https://codepen.io/syuji-higa/pen/zyOrQm/">Animation GLSL ShaderArt (Raymarching)</a> by Syuji Higa (<a href="https://codepen.io/syuji-higa">@syuji-higa</a>) on <a href="https://codepen.io">CodePen</a>.</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

そして、これがレイマーチング。シェーダアートを三次元に引き上げたものと考えるとよいでしょうか。今回は光源はいらないので法線の処理とかも省きました。おかげでレイマーチングらしさは感じられません。その描画コストは今回紹介したなかでも圧倒的に高く、記述も難しいですが、そのかわり表現できることの幅がふくらみます。

弱点はもちろんマシンパワーに頼る部分が大きいというところですが、もはやそういうことを言うのは野暮というものでしょう。

シェーダのライブコーディングバトルを見たことがありますでしょうか。とても不思議な世界を限られた短い時間で構築していくさまは圧巻です。仕事なんて忘れて楽しんでみませんか。

# そして、これから
冒頭にて、まるでアニメーションをよく思っていないような話をしましたが、ここまで読んでくれて方なら分かってもらえるでしょう。私はアニメーションを愛しています。まあ、私よりずっとずっと愛している人がいるのは知っています。ただ、私もそのはしくれのひとりなのだということです。ならばアニメーションそのものについて書けばよいのでしょうけれど、まあ実力不足ではありますし、何よりもアニメーションを嫌いになりそうな自分がいました。アニメーションは私を裏切らないけれども、私はといえばどうしたものか。ここ数年で Web サイトをつくる上でやらなくていけないことが本当に増えてきています。そんななかで忙さに翻弄されて、Web サイトの本質を忘れ、ユーザのことを考えず、アニメーションは雑になり、それでもちゃんと実装しようと体は疲弊していくばかり。これでは恥ずかしくて、恥ずかしくて、面と向かって愛を語ることなどできはしない。だからこそ、この場にてアニメーションと向き合い、まずは楽しく実装をする方法を、状況によって適切な手法を選ぶことを、そしてよいアニメーションを考えることができるように、さまざまな実装方法を洗い出してみました。まあ、大きくなにかが変わるわけではないですが、きちんとコストを考えて、Web サイトの本質やユーザのことを忘れず、楽しくアニメーションを実装してけるとよいなと考えています。とはいえ、どの手法でもアニメーションの実装はまだまだ大変だと思います。それでも日進月歩で、より気楽に、より面白く、より自然にアニメーションを実装できるようになるでしょう。理想としては想像したものが自動で動き出すことですかね。それは見果てぬ夢かもしれませんが、そんな未来をどこまでも追いかけ続けようと思います。

えっ？ Flash！？ えっと、忘れてた。。。