JavaScript
SVG
Snap.svg

Snap.svgでsvgパスを動かそう! ①入門編

概要

個人ポートフォリオサイト を作っている中で、何か シャレオツ な動きを入れたいなーと思いザッと調べてみたところ、SVGパスを動かすことができる Snap.svg というライブラリを見つけ、触り程度ですが動かしてみました。

Snap.svgとは?

jQueryライクでのSVG内のパス指定が可能で、サイズや色、さらにはアニメーションまで設定することが出来るライブラリです。

似たようなsvg操作用ライブラリ

  • Raphaël.js
    Snap.svgと同じ製作者のライブラリです。Snap.svgの前身のようなものなので、今から学ぶのであればSnap.svgで良いと思います。

  • SVG.js
    こちらもjQueryライクのSVG操作が可能です。こちらは、「The lightweight library for manipulating and animating SVG.」と言っている通り、SVGを操作したりアニメートさせたりするための軽量なJavaScriptライブラリとなっています。

  • BonsaiJS
    こちらはキーフレームアニメーションを設定することが可能なライブラリです。また、フィルター処理やモーフィングも可能とのことです。

使い方

完成例

今回は非常にシンプルな以下のようなアニメーションを実現してみます。

snap.gif

SVGファイルはこんな感じです。

logo.svg
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
<svg version="1.1" id="レイヤー_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px"
     y="0px" viewBox="0 0 184.3 184.3" style="enable-background:new 0 0 184.3 184.3;" xml:space="preserve">
<g id="all">
    <g id="back">
        <polygon id="box" points="4.9,44.8 4.9,140.8 93.3,182 179.8,139 179.8,44.8 92.4,2.3         "/>
    </g>
    <g id="front">
        <g id="colors">
            <polygon id="blue" points="10.9,52.4 10.6,90.9 10.9,136.1 9.4,137 89.9,173.9 89.9,90.9          "/>
            <polygon id="green" points="174.7,50.6 95.7,90.6 95.1,90.2 94.9,90.9 94.9,173.9 174.7,135.9 174.9,90.9          "/>
            <polygon id="red" points="169.5,45.9 92.4,8.5 15.1,45.9 10.9,45.9 92.4,85.1 173.7,45.9          "/>
        </g>
    </g>
    <g id="frames">
        <path id="frame" d="M92.4,2.3L4.9,44.8v96L93.3,182l86.5-43V44.8L92.4,2.3z M53.9,157v-27.4l-5-3.1v28.2l-38-17.7V52.5l38,18.5
            v24.4l5,2.9V73.4l36,17.5v24.4l-18.8,7.4L89.9,142v31.7L53.9,157z M92.4,85.2L14.2,47L92.4,9l78,38l-18.2,8.9h-42l9.9,15.8
            L92.4,85.2z M139.9,152v-26.3l-5.5,3.7l0.4,25.1l-39,19V90.9l78-39.4v45.7l-23.5,12.1l23.5,14.2v12L139.9,152z"/>
        <polygon id="red_box_under" points="47.5,57.3 69.9,68.2 91.4,57.3 69.4,46.8         "/>
        <polygon id="red_box_over" points="91.5,35.8 113.9,46.8 135.4,35.8 113.4,25.3       "/>
        <polygon id="green_box_over" points="131.1,111.4 153.3,100.1 152.5,76.4 130.9,87.6      "/>
    </g>
</g>
</svg>

手順

ダウンロード

公式 から最新のZipをダウンロードします。

読み込み

snap.svg-min.jsファイルを読み込みます。

screencapture- 2017-12-13 23.16.27.png

index.html
・・・
<script type="text/javascript" src="snap.svg-min.js"></script>
・・・

流し込むタグを用意

以下のsvgタグに挿入します。

index.html
・・・
<script type="text/javascript" src="snap.svg-min.js"></script>
・・・
<div>
  <img>
    <svg id="target"></svg>
  </img>
</div>
・・・

JavaScriptの実装

最終的にこんな感じ

animate.js
jQuery(document)
    .ready(
        function() 
        {
            var snap = Snap("#target"); //流し込み対象のDOMを取得
            var grop = snap.group(); //Groupの作成

            Snap.load("logo.svg", function(data) //SVGファイルを読み込んでコールバック関数で処理
                      {
              grop.append(data); //データをDOMに追加

              var all = Snap.select("#all"); //一番外側のグループを取得
              var allBbox = all.getBBox(); //描画領域の短形範囲を取得
              var box = Snap.select("#box"); //最初に表示する黒背景の6角形パスを取得(途中で縮小)
              var frames = Snap.select("#frames"); //後から表示する黒枠フレームのパスを取得(途中で拡大)
              var red = Snap.select("#red"); //赤エリアのパスを取得(途中で拡大)
              var blue = Snap.select("#blue"); //青エリアのパスを取得(途中で拡大)
              var green = Snap.select("#green"); //緑エリアのパスを取得(途中で拡大)

              box.transform("s0"); //初期非表示化
              frames.transform("s0"); //初期非表示化
              red.transform("s0"); //初期非表示化
              blue.transform("s0"); //初期非表示化
              green.transform("s0"); //初期非表示化

              var redFunc = function() //赤エリアのパスのアニメーション定義
              {
                red.animate({
                  transform: 's1',
                  fill: "#FF0000"
                }, 3000, mina.bounce)
              };

              var blueFunc = function() //青エリアのパスのアニメーション定義
              {
                blue.animate({
                  transform: 's1',
                  fill: "#0000FF"
                }, 3000, mina.bounce)
              };

              var greenFunc = function() //緑エリアのパスのアニメーション定義
              {
                green.animate({
                  transform: 's1',
                  fill: "#39B44A"
                }, 3000, mina.bounce)
              };

              var colorsFunc = function() //赤,青,緑エリアのパスのアニメーションの順番定義
              {
                redFunc();
                setTimeout(function() {
                  blueFunc();
                  setTimeout(function() {
                    greenFunc();
                  }, 500);
                }, 500);
              }

              var boxFunc = function() //全体的なアニメーションの順番定義
              {
                box.animate({ 
                  transform: 's1' 
                }, 2000, mina.bounce, function() {
                  colorsFunc();
                  frames.transform("s1");
                })
              };

              boxFunc(); //実行
            }
       });
    );

わからないこと

  • animate関数の第一引数のtransformに指定する値のルールがいまいち理解出来ていない。
  • もっとダイナミックに動かす方法
  • パスのモーフィング出来る?

この辺はまた機会があれば別記事にてまとめようと思います!