JavaScriptでSVGアニメーション(フロントエンドエンジニア向け)

SVGはDOMの仕様に準拠している(※)ので、一定時間毎にJavaScriptからDOMを操作することでアニメーションを実現できます。例えば、円の色を徐々に赤色にするのは次のコードです。

let time = 0;
let myCircle = document.querySelector("#myCircle");
function animate() {
  time += 1;
  requestAnimationFrame(() => {
    let l = time;
    myCircle.style.fill = `hsl(0, 100%, ${l}%)`;
    time += 1;
    if (time < 50)
      animate();
  });
}
animate();

※ DOM Level 2に準拠しています(参考:「SVG Document Object Model (DOM) – SVG 1.1 (Second Edition)」)

JavaScriptのメリットは、表現力の高さです。塗りと線の変化、拡縮・回転・移動、パスの変形、パスに沿ったアニメーション等、あらゆるアニメーションが可能です。CSSプロパティやSMILで実現できたものは、全て実現できます。また、IE 11、Microsoft Edgeを含む主要ブラウザーで動作します。ただ、前述のコードを見ても分かる通り、CSSやSMILに比べると、コードが煩雑で実装難易度は高めであると言えます。

ライブラリを使って効率的にJavaScriptアニメーションを実装する

JavaScriptのアニメーションは、ライブラリを用いることで効率的に実装できるようになります。

今回は、2つのライブラリを紹介します。

JavaScriptでのSVG要素の操作を楽にする「Snap.svg」

Snap.svgを用いると、jQueryライクな記法でJavaScriptによるSVG操作が可能になります。前述の円を徐々に赤色にするアニメーションは、次のように少ないコード量で可能です。

// #myCircleの要素を取得
var myCircle = Snap("#myCircle");
// #myCircleのfillプロパティを1秒かけてredにする
myCircle.animate({
  "fill" : "red"
}, 1000);

Snap.svgを用いてアニメーションを行っている様子は次の通りです。

手書き風の演出を楽にするvivus

vivus(ヴィヴス)は、手描き風のアニメーションを実現するライブラリです。次のコードを記述するだけで、手描き風のアニメーションが実現できます。

new Vivus("SVG要素のID", {duration: (速度)});

vivusを用いてアニメーションを行っている様子は次の通りです。

手描き風のアニメーションはCSSアニメーションやSMILでも実装できますが、vivusの場合はJavaScriptアニメーションになるため対応ブラウザーが多いです。速度変更、遅延実行、複数のラインの同時アニメーション、順次アニメーションなど豊富なオプションが使えることも魅力です。

Snap.svgとvivusを組み合わせたデモ

2つのライブラリを使用して、不動産のウェブサイトをイメージしたコンテンツを作成しました。不動産のウェブサイトをイメージしたオリジナルデモを作成しました。次のリンクよりご覧ください。

ページをスクロールすると、適切な位置に達した場合にvivusによるアニメーションが開始します。自前で実装する場合に面倒な、特定位置にスクロールした際の処理についても、vivusを使えば手軽に実装できます。コンテンツ下部の地図部分は、vivusによるアニメーションが完了した後に、透明だった塗りが不透明になり、同時に上部からピンが降りてくる演出が行われます。これらはSnap.svgで実装したものです。

地図部分の具体的なコードは次のとおりです。ライブラリを駆使することで少ないコードで実現可能です。

// 地図のピンを上部に固定しておく
Snap("#mapPin").attr({
  transform: "translate(0, -400px)"
});

// 地図のラインアート
new Vivus("map", {duration: 60}, function () {
  // #map内のpathの塗りの透明度を1にする
  Snap("#map").selectAll("path").animate({
    "fill-opacity": 1
  }, 60, function () {
  });

  // 地図のピンを下ろす
  Snap("#mapPin").animate({
    transform: "translate(0, 0px)"
  }, 120, mina.easeout);
});

▲ 地図部分の演出

最後のページでは、動画作成作成ソフトを使ってSVGアニメーションを実現する方法(デザイナー向け)、SVGの学習に役立つ参考資料を紹介します。