SVGループアニメーションの作り方
鳥が羽ばたくとか、人が歩くとか、繰り返しの動作は多い。
繰り返しアニメーションは、アニメの基本である。
SVG を使ったループアニメーションの作成方法について考察する。なお、ここでは、JavaScript は使わず、SVGだけで実現する方法について述べる。
SVG SMIL アニメーション
SVG(Scalable Vector Graphics)は、ベクトル図形を表現する方法と思っている人も多いと思うが、実は、アニメーションを表現する機能をもっている。
現在では、Internet Explorer を除く、ほとんどのブラウザが、SVG SMIL アニメーションをサポートしており、iPhone や、Android でもプラグインなしで再生できる。どのブラウザで再生できるかは、ここを見よう。
図形1つの繰り返し
SVGは、円を書いて動かすだけなら簡単である。まず、コードをみていただこう。
<svg> <circle fill="blue" cx="150" cy="100" r="50" /> <circle fill="orange" cy="100" r="20" > <animate attributeName="cx" from="50" to="250" dur="5s" repeatCount="indefinite" /> </circle> </svg>
青い玉の手前をオレンジの玉が何回も横切ることになる。
- この動作を確かめるには、CodePenを使うとよい。このサイトを Chrome / Firefox/ Safari などで開き、上の「New Pen」ボタンをクリックし、HTMLの中に、上のSVGのソースをペーストするとアニメーションが見える。ソースを修正するとより理解が進むだろう。
- 簡単に説明すると、fillは色、cx,cy は中心座標、r は半径。
- <animate がアニメーションの指定で、attributeNameで指定された cx(中心のX座標) を、5秒(dur="5s")で、50から250まで(from="50" to="250")変化させる。repeatCount="indefinite" が無限ループ設定だ。
立体的にまわる(玉が2つ)
次に、青い玉のまわりを立体的に回るようにしてみよう。
下のように2つの玉を組み合わせれば、立体的に回るように見える。
<svg> <circle fill="orange" cy="100" r="20"> <animate attributeName="cx" from="250" to="50" dur="5s" repeatCount="indefinite" /> </circle> <circle fill="blue" cx="150" cy="100" r="50" /> <circle fill="orange" cy="100" r="20"> <animate attributeName="cx" from="50" to="250" dur="5s" repeatCount="indefinite" /> </circle> </svg>
立体的にまわる(玉が1つ)
では、一つの玉が回るようにするにはどうしたらよいか。
その場合、一つの玉が動いている間、もう一つの玉を消しておかないといけないので、もはや、repeatCount="indefinite" は使えない。
2つの玉に、ラベル(id="o1", id="o2")をつけて、
もう片方の玉の動作が終了(o1.end、o2.end)したら
スタート(begin)するようにするしかない。
<svg> <circle fill="orange" cx="-50" cy="100" r="20"> <animate id="o1" begin="0;o2.end" attributeName="cx" from="250" to="50" dur="5s" /> </circle> <circle fill="blue" cx="150" cy="100" r="50" /> <circle fill="orange" cx="-50" cy="100" r="20"> <animate id="o2" begin="o1.end" attributeName="cx" from="50" to="250" dur="5s" /> </circle> </svg>
では、これがもっと複雑なアニメーションになったらどうするのか?
このように、id=xxx と、begin=xxx.end をつけていく方法では、図形の数が増え、動きが複雑になると、id の数が半端でなくなる。さらに、間に別のコマを挿入したくなったとき、idのつなぎかえが発生することになり、大変なことになる。
相対時間で指定するループアニメーション
これを解決するために、以下のように、ダミーの <rect>
ループをもうけ、それに対する相対時間で動作を指定する方法を考えたので紹介する。コードは以下のようになる。この方法であれば、id=xxxは、ループアニメーション1つに対して、1つ定義すればよい。内部の動作は、相対時間で指定する。多くの時間は、各図形に対して共通なので、もし修正が発生しても、文字列の一括置換で容易に変更できる。
<svg> <rect> <animate id="o1" begin="0;o1.end" dur="10s" attributeName="visibility" from="hide" to="hide"/> </rect> <circle fill="orange" cx="-50" cy="100" r="20"> <animate begin="o1.begin" attributeName="cx" from="250" to="50" dur="5.05s"/> </circle> <circle fill="blue" cx="150" cy="100" r="50" /> <circle fill="orange" cx="-50" cy="100" r="20"> <animate begin="o1.begin+5s" attributeName="cx" from="50" to="250" dur="5.05s"/> </circle> </svg>
-
<rect>
が10秒間隔(dur="10s")を作るダミーの図形である。id="o1" begin="0;o1.end" によって10秒ごとに起動する。"0;o1.end"は起動条件が、0秒もしくは、o1が終了したときの2つあることを意味する。 - attributeName="visibility" from="hide" to="hide"の部分は、ほかの命令でもよいが、とりあえず、見えない属性を設定している。
- id="o1"が10秒ごとに起動するので、玉は、o1と同時(begin="o1.begin")もしくは、o1の5秒後(begin="o1.begin+5s")にスタートさせる。
- 玉が移動する時間を5.05秒(dur="5.05s")としているのは、5秒きっちりにするとブラウザによってちらつきが生じるためだ。
SVGループアニメーションの例
この方法を用いたループアニメーションの例を、CodePenにあげた。(こちら Komori's SVG Animation)IE以外なら、ほぼ見えるはずである。IE は SVG のSMILアニメーションをサポートしていないため、静止画にしかならない。
SVGループアニメーションが作れるエディタ
Ubuntu, もしくは、Raspberry Pi で動作するエディタ「9va-pi」がここからダウンロードできる。Raspberry Pi は 4000円程度で購入できるし、Ubuntu は、中古のXPパソコンを入手すれば、OSは無料である。Windows版「9va-win」, [Macintosh版「9va-mac」 もあり。