SVGアニメーション はじめの一歩
前提
SVGの埋め込み方法はいくつか用意されています。
- img要素のsrc属性による埋め込み
- object要素のdata属性による埋め込み
- embed要素のsrc属性による埋め込み
- CSSプロパティ(背景画像や擬似要素)による埋め込み
- インラインSVGによる埋め込み
基本的にSVGをアニメーションさせる際、JavascriptからDOM要素として取得し、属性値を変化させることで制御するため、 アニメーションに用いたい場合は必ずインラインSVGにて読み込んでください。
アニメーションの方法
基本的にはJavascriptにて制御する方法がセオリーであると先述してしまいましたが、実のところ方法としてはJavascript制御のほかにanimate要素を用いる方法もあります。
animate要素による制御
アニメーションさせたい要素の子要素としてanimation要素を定義します。
変化させたい属性と値を記述することでアニメーションが可能です。
IEとEdgeが未対応であること、任意のタイミングでの制御、複雑な制御には対応しにくい実制作においては不向きといって良いでしょう。
以下の例をIEとEdgeで表示してもアニメーションしないことがわかります。
See the Pen SVG Demo - 01 by Shin Imae (@shinimae) on CodePen.
このanimate要素というものは、そもそもマルティメディアを扱うXMLの拡張様式であるSMIL(Synchronized Multimedia Integration Language)という技術にて提供されているAPIなのですが、まだまだ仕様が不安定で、ブラウザ対応も不透明なようです。
実際に、Chromeにおいても2015年より非推奨扱いとなっているようです。
SMIL animate要素のリファレンスも以下にご案内しておきますので、興味のあるかたは併せて参照してみるとより理解が深まるでしょう。
Javascriptによる制御
ということで、基本的には先述した通りDOM要素として取得し属性値を変化させることで動かします。
そのためVelocity.jsなどのアニメーションライブラリでも制御が可能ですし、CSSで変化させることもできます。
しかし後述いたしますがCSSによるアニメーションはブラウザ対応が充分ではなく、パスを変化させることによるモーフィングもできないため、Javascriptによる制御が王道と言えるでしょう。
以下の例は、Velocity.jsによって円の半径を変化させるサンプルです。
See the Pen SVG Demo - 02 by Shin Imae (@shinimae) on CodePen.
この例では circle要素の属性値を変化させていますが、line要素、path要素の属性値も変化させることが可能です。
これらの要素を制御することで曲線の描画やモーフィングなどHTMLにおけるDOM要素では不可能であった表現が可能になります。
ここからは、ニーズの高いアニメーションの方法についてケースごとにまとめてゆきます。
ラインアニメーション
ペンで描いたようなアニメーションです。
See the Pen SVG Demo - 03 by Shin Imae (@shinimae) on CodePen.
SVGにはpath要素を破線として描画する機能があり、その性質を逆手に取っています。
以下の記事に詳細が解説されている通り、path要素の全長に等しい値をstroke-dashoffset/stroke-dasharrayに指定します。
SVGのアニメーションで線を引く方法まとめ(IEへの対応も)|2.IDEA
アニメーションさせるにはstroke-dasharrayを0へと変化させることで実現できます。
0へと変化させるにはいくつか方法がありますが、基本的にはjQueryのanimateメソッドか、それを拡張した各種ライブラリのメソッドを使うのが良いでしょう。
ちなみに、CSSプロパティ(transition/animation)を利用してアニメーションさせる方法もありますが、残念ながらIEが未対応です(通常のDOM要素には対応しているため、SVGの属性値に対して未対応といった方が正しいでしょう)。
このように、原理がわかってしまえば実装は非常に容易なのですが、注意点が2点あります。
一つは、d要素にて指定された座標に沿って動くため、Illustratorなどのデザインツールで作成する際に点を打った「書き順」がそのままアニメーションの方向になること。
そしてもう一つはその「書き順」がそのままアニメーションの方向になるがゆえに、「線を描く方向」などの制御にはある程度の限界があること。
どうしても細かく制御したい場合は複数のpathに細分化したものをg要素にまとめ、それぞれにラインアニメーションを走らせたり、Canvasを用いたアニメーションにシフトするなどの対応が必要になります。
パスに沿ったアニメーション
See the Pen SVG Demo - 04 by Shin Imae (@shinimae) on CodePen.
こちらはネイティブにサポートされているメソッドを用いることで容易に実装が可能です。
getPointAtLengthというメソッドは任意の長さを引数にとり、対応する座標を返すものです。
連続的に引数の値を増減しながら動かす対象の座標を設定し続けることで、パスに沿ったアニメーションが可能になります。
ですので、animateメソッドにて実装することは難しく、パラパラ漫画の要領で一定時間ごとに描画処理を呼び出すことで実装します(jQueryでも内部的にはそのように実装されています)。
もしイージングを持たせたい場合は関数としてイージングを定義し、描画のタイミングでその関数を通してアニメーションさせる値を制御します。
イージングの仕組みについて、基礎的な考え方はこちらを参照ください。
アニメーションさせたい時間に対する現在の経過時間の割合を算出し、それをn次関数や三角関数に当てはめることで、適用する値を算出します。
以下の例ではeaseOutCubicというイージングを与えています。
See the Pen SVG Demo - 04 (with Easing) by Shin Imae (@shinimae) on CodePen.
曲線の制御(パスモーフィング)
SVGの最大の利点のひとつに、曲線の表現が可能であるという点があります。
この利点を活かし、通常のDOM要素では実現が不可能な、曲線を制御するアニメーションを行うことができます。
path要素のd属性に指定されている座標を連続的に変化させることで実装するのですが、場合よっては難易度の高い理論を求められるため、pathの制御に特化したライブラリを使用するのが良いでしょう。
パスを変化させるロジックはライブラリ側で吸収してくれるため、制作者はコア機能の開発のみに注力できます。
以下は、使い勝手の良いライブラリの一つ、Snap.svgを用いたパスモーフィングの例です。
ご覧の通りjQueryライクに記述ができるため、パスモーフィング実装の垣根がぐっと下がります。
See the Pen SVG Demo - 05 by Shin Imae (@shinimae) on CodePen.
パスモーフィングは、pathの座標を徐々に変化させることで実現するため、変化前と変化後の座標の数を同一にしておかなければいけません。 しかし、それさえ注意すればライブラリの力を借りて比較的短時間で実装ができます。
また、回転や色の変化も併用することで、よりインタラクティブな動きも実装可能です。
See the Pen SVG Demo - 06 by Shin Imae (@shinimae) on CodePen.
インフォグラフィック
昨今流行しているSVGによるインフォグラフィックも、ライブラリの使用により容易に実装できます。
いくつかライブラリが公開されていますが、その中でもD3.jsが有用かと思います。
例えば、以下はオーソドックスなパイチャートですが、こういったものもD3独自のメソッドをおさえるだけで比較的短時間で実装できます。
制作者はデータのバインディングとチャートのサイズ・位置のみ気にすればよく、面倒なロジックは全てD3.js側で吸収してくれています。
また基本的なアニメーションもD3.js側で用意してあるため、以下のようなJSON形式のデータから生成するインタラクティブなグラフも比較的短時間で実装できます。
こちらもSnap.svgと同様に、細かいロジックはD3.jsで吸収される分、制作者はコアとなる機能の開発を行うのみで済みます。
See the Pen D3.js Demo - 01 by Shin Imae (@shinimae) on CodePen.
See the Pen D3.js Demo - 02 by Shin Imae (@shinimae) on CodePen.
おわりに
ここに挙げたものはあくまでも基本的な方法を一通り紹介したにすぎません。
しかし難易度が高いと思われがちなSVGアニメーションも紐解いてしまえば、一つ一つはとてもシンプルなものであることはよく分かります。
一見すると複雑なアニメーションも、実のところはシンプルなロジックの集まりであったりするので、今回の記事がきっかけでSVGアニメーション実装の一助となりましたら幸いです。