お役立ちコラム
JavaScript

SVGを自在に変形!JSライブラリ「Snap.svg」を使ってモーフィング表現を実装する方法

※本記事には広告が含まれます

JSライブラリ「Snap.svg」を使用すると、異なるpathで描いたSVG画像をスムーズに変形アニメーションさせられます。

このように、連続する2つの画像の間をコンピューターグラフィックスによって補間し、自然な変形を実現する技術を「モーフィング」と呼びます。

今回は、このモーフィングをJavaScriptライブラリ「Snap.svg」で実装する方法を解説します。

Snap.svgとは?

Snap.svg 公式サイト スクリーンショット

公式サイト:http://snapsvg.io/
ドキュメント:http://snapsvg.io/docs/

Snap.svgはAdobeが開発したJavaScriptライブラリです。

Snap.svgを使えば、JavaScriptからSVGを制御でき、アニメーションやクリック、ホバーなどのイベント処理を手軽に実装できます。

なお、Snap.svgは Apache License 2.0 の下で配布されており、オープンソースとして商用利用を含め無料で利用できます。

Snap.svgの使い方

Snap.svgのダウンロード方法

Snap.svgをプロジェクトに取り込むには以下の3つの方法があります。

Snap.svgをプロジェクトに取り込む方法
  1. 公式サイトからファイルをダウンロードしてくる方法
  2. CDNを使う方法
  3. npmを使う方法

本記事では2番目のCDNを使う方法でSnap.svgの使い方を解説します。

SVGコードをアニメーションさせる方法

本例では、Snap.svgを用いてSVGコードで書かれた円(circle)をJavaScriptでアニメーションさせる基本手順を解説します。

<svg id="sample" width="200" height="200" viewBox="0 0 200 200">
  <circle id="circle" cx="100" cy="100" r="100" fill="#ccc" />
</svg>

まずは、headタグの中に以下の行を追記します。

<script src="https://cdn.jsdelivr.net/npm/snapsvg@0.5.1/dist/snap.svg-min.min.js"></script>

これでSnapがブラウザのグローバルオブジェクトに公開され、利用できるようになります。

続いて、Snapでアニメーション対象のcircleを取得します。

Snap(“CSS selector”)と書くことで、指定したセレクターにマッチするSVG全体をラップできます。

document.addEventListener("DOMContentLoaded", function () {
  const s = Snap("#sample");

});

さらに円要素を取得したい場合は、select(“CSS selector”)メソッドを使用します。

document.addEventListener("DOMContentLoaded", function () {
  const s = Snap("#sample");
  const circle = s.select("#circle");
});

アニメーションさせたい要素が取得されたら、あとはanimate(attrs, duration, [easing], [callback])メソッドを使って、取得した円要素をどのようにアニメーションさせたいか指定します。

4つのパラメーターの意味は以下の通りです。

パラメーター概要
attrsオブジェクト変更先の属性を表すキーと値の組み合わせを指定
duration数値アニメーションの継続時間をミリ秒で指定
easing(任意)関数イージング関数(あらかじめ用意されているmina関数、または独自に用意した関数)を指定
callback(任意)関数アニメーション終了後に呼び出したいコールバック関数を指定
document.addEventListener("DOMContentLoaded", function () {
  const s = Snap("#sample");
  const circle = s.select("#circle");

  circle.animate({ r: 50 }, 1000, mina.easeinout);
});

これで、半径100pxの円が、一秒間かけて半径50pxにまで小さくなっていくアニメーションを実装できました。

Snap.svgには、他にも様々なメソッドが用意されており、非常に多くのことができます。興味がある方はぜひドキュメントを見てみて下さい。

document.addEventListener("DOMContentLoaded", function () {
  const s = Snap("#sample");
  const circle = s.select("#circle");

  function shrink() {
    circle.animate({ r: 50 }, 1000, mina.easeinout);
  }

  function expand() {
    circle.animate({ r: 100 }, 1000, mina.easeinout);
  }

  circle.hover(shrink, expand);
});

Snap.svgを使って異なるpathで描いたSVG画像をスムーズに変形(モーフィング)させる方法

次に、Snap.svgをSVGモーフィングを実装する方法を解説します。

まずは、変化前の図形をイラストレーターを使って作成します。

続いて、viewBoxを揃えたいため、同じキャンバス上に変化前の図形を複製し、変化後の図形を作成します。

一点、モーフィングを実装する際は、変化前と変化後の図形でアンカーポイントを同数にしておかないと、綺麗にアニメーションされないため注意しましょう。

「ファイル>別名で保存」からSVG形式で保存します。

以上で、変化前と変化後のアイコンのSVGコードが取得できました。

イラストレーターでは書き出し時に不要な記述が付いてくるため、不要な部分のみあらかじめ削除しておきます。

<svg viewBox="0 0 1000 1000" width="200" height="200">
  <defs>
    <style>
      .st0 {
        fill: #b3b3b3;
      }
    </style>
  </defs>
  <path
    class="st0"
    d="M989.1,500c0,131.9-52.2,251.6-137.1,339.6-89,92.2-213.8,149.6-352.1,149.6s-275.6-63.3-365.2-163.7C57.7,739,10.9,625,10.9,500c0-119.8,43-229.5,114.5-314.5C215.1,78.7,349.6,10.9,500,10.9c132.7,0,253.1,52.8,341.2,138.6,91.3,88.9,148,213.1,148,350.5Z"
  />
  <path
    class="st0"
    d="M989.1,500c0,131.9-226.3,77.5-311.2,165.5-89,92.2-39.7,323.7-178,323.7s-109.1-229.8-198.6-330.3C224.3,572.4,10.9,625,10.9,500c0-119.8,202.2-70.4,273.6-155.4C374.2,237.8,349.6,10.9,500,10.9c132.7,0,104.7,218,192.8,303.8,91.3,88.9,296.3,47.9,296.3,185.3Z"
  />
</svg>

次に、Snap.svgで各pathを操作できるようにするため、svgとpathにid属性を付与します。

また、変化後のpathはdisplay:noneとして初期状態では表示されないようにします。

<svg viewBox="0 0 1000 1000" width="200" height="200" id="sample">
  <defs>
    <style>
      .st0 {
        fill: #b3b3b3;
      }
    </style>
  </defs>
  <path
    id="beforePath"
    class="st0"
    d="M989.1,500c0,131.9-52.2,251.6-137.1,339.6-89,92.2-213.8,149.6-352.1,149.6s-275.6-63.3-365.2-163.7C57.7,739,10.9,625,10.9,500c0-119.8,43-229.5,114.5-314.5C215.1,78.7,349.6,10.9,500,10.9c132.7,0,253.1,52.8,341.2,138.6,91.3,88.9,148,213.1,148,350.5Z"
  />
  <path
    id="afterPath"
    style="display: none"
    class="st0"
    d="M989.1,500c0,131.9-226.3,77.5-311.2,165.5-89,92.2-39.7,323.7-178,323.7s-109.1-229.8-198.6-330.3C224.3,572.4,10.9,625,10.9,500c0-119.8,202.2-70.4,273.6-155.4C374.2,237.8,349.6,10.9,500,10.9c132.7,0,104.7,218,192.8,303.8,91.3,88.9,296.3,47.9,296.3,185.3Z"
  />
</svg>

Snap(“CSS selector”)select(“CSS selector”)メソッドを使って、Snap.svgから各pathを操作できるようにします。

document.addEventListener("DOMContentLoaded", function () {
  const s = Snap("#sample");
  const beforePath = s.select("#beforePath");
  const afterPath = s.select("#afterPath");

 
});

attr()メソッドを使って、beforePath、afterPathのd属性の値を取得します。

document.addEventListener("DOMContentLoaded", function () {
  const s = Snap("#sample");
  const beforePath = s.select("#beforePath");
  const afterPath = s.select("#afterPath");

  const dBeforePath = beforePath.attr("d");
  const dAfterPath = afterPath.attr("d");
});

最後にanimate(attrs, duration, [easing], [callback])メソッドを使って、第一引数attrsの中で変更後のd属性の値を指定します。

パラメーター概要
attrsオブジェクト変更先の属性を表すキーと値の組み合わせを指定
duration数値アニメーションの継続時間をミリ秒で指定
easing(任意)関数イージング関数(あらかじめ用意されているmina関数、または独自に用意した関数)を指定
callback(任意)関数アニメーション終了後に呼び出したいコールバック関数を指定
document.addEventListener("DOMContentLoaded", function () {
  const s = Snap("#sample");
  const beforePath = s.select("#beforePath");
  const afterPath = s.select("#afterPath");

  const dBeforePath = beforePath.attr("d");
  const dAfterPath = afterPath.attr("d");

  beforePath.animate({ d: dAfterPath }, 1000, mina.easeinout);
});

これでモーフィングが実装できました。

なお、上の例ではbeforePathからafterPathへの変形が一度だけ行われましたが、以下のように書くことで、beforePathとafterPathを交互に変化させ続けることができます。

document.addEventListener("DOMContentLoaded", function () {
  const s = Snap("#sample");
  const beforePath = s.select("#beforePath");
  const afterPath = s.select("#afterPath");

  const dBeforePath = beforePath.attr("d");
  const dAfterPath = afterPath.attr("d");

  function svgMorphAnimation(toAfter = true) {
    beforePath.animate(
      { d: toAfter ? dAfterPath : dBeforePath },
      1000,
      mina.easeinout,
      function () {
        svgMorphAnimation(!toAfter);
      }
    );
  }
  svgMorphAnimation(true);
});

まとめ

今回はSnap.svgの基本的な使い方、SVGモーフィングを実装する方法を解説しました。

Snap.svgが使えるようになると表現の幅が広がるため、ぜひこの機会にマスターしてみて下さい。

今回は以上になります。最後までご覧頂き、ありがとうございました。

HOMEお役立ちコラムJavaScriptSVGを自在に変形!JSライブラリ「Snap.svg」を使ってモーフィング表現を実装する方法