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

# 概要

[ **個人ポートフォリオサイト** ](http://portfolio.bakira-tech.com/)を作っている中で、何か **シャレオツ** な動きを入れたいなーと思いザッと調べてみたところ、`SVG`パスを動かすことができる[ **Snap.svg** ](http://snapsvg.io/)というライブラリを見つけ、触り程度ですが動かしてみました。


# Snap.svgとは？

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

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

- [ **Raphaël.js** ](http://dmitrybaranovskiy.github.io/raphael/)
  `Snap.svg`と同じ製作者のライブラリです。`Snap.svg`の前身のようなものなので、今から学ぶのであれば`Snap.svg`で良いと思います。

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

- [ **BonsaiJS** ](http://bonsaijs.org/)
  こちらはキーフレームアニメーションを設定することが可能なライブラリです。また、フィルター処理やモーフィングも可能とのことです。


# 使い方

## 完成例

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

![snap.gif](https://qiita-image-store.s3.amazonaws.com/0/113654/4cbb3613-8b87-1081-4fe6-c5269d29adba.gif)

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

```xml: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>
```

## 手順

### ダウンロード

[ **公式** ](http://snapsvg.io/)から最新の`Zip`をダウンロードします。

### 読み込み

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

<img width="826" alt="screencapture- 2017-12-13 23.16.27.png" src="https://qiita-image-store.s3.amazonaws.com/0/113654/aa675b9a-585a-3254-2d34-af0c696fdac8.png">


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

### 流し込むタグを用意

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

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

## JavaScriptの実装

最終的にこんな感じ

```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`に指定する値のルールがいまいち理解出来ていない。
- もっとダイナミックに動かす方法
- パスのモーフィング出来る？

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