HTMLのみで簡単にSVGモーフィングを実装してみた

SVGモーフィングは、Scalable Vector Graphics（SVG）を使用して、2つ以上の異なる図形やパス間で滑らかなアニメーションを実現する手法です。
モーフィングとはある画像から別の画像へ、連続的に変形させる画像表現です。

SVGモーフィングを実装する方法はさまざまあり、CSSやJavaScriptでも実装が可能ですが、HTMLだけでも実装が可能です。

# 準備.2つの異なるSVGパスを用意する

Illustratorなどで2種類のSVGファイルを作成します。
作成の注意点としては、パスのアンカーポイント数は同じ数である必要があります。
6つのアンカーポイントをもつ図形を2種類用意しました。

![thumb_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3561753/cd343b33-c6c8-c5c5-eebb-944492355149.png)

※Illustratorのペンツールで適当に流体っぽい図形を作りました。

Aの図形を開始点、Bの図形を終了点とします。

# 1.SVGのパス変化させてみる

まずはAの図形からBの図形へと変化するような動きをつけてみます。

完成した動きがこちらです。

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="YzBEerm" data-user="fg_noguchi" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/fg_noguchi/pen/YzBEerm">
  【HTMLでSVGモーフィング.1】SVGのパス変化させてみる</a> by Noguchi (<a href="https://codepen.io/fg_noguchi">@fg_noguchi</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

Aの図形のSVGファイルをエディタで開いたものをベースにして作成します。
Illustratorで生成される余計なタグなどは適宜削除します。

```html
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 300">
    <path d="m81.74046,16.55315C41.90248,36.52574,3.28772,94.20846.27031,140.59994c-3.53709,54.38138,28.16252,109.92764,64.37148,130.09785,46.43306,25.86555,83.48176,37.31489,139.8068,23.19574,65.31875-16.37362,95.55141-87.15212,95.55141-139.17445,0-34.70957-3.61902-89.99445-61.35406-130.09785C193.41852-6.79422,128.00746-6.64259,81.74046,16.55315Z"/>
</svg>
```

`path`内に`animate`を追加して、必要な設定をしていきます。

```html
<path d="開始点のパス">
<animate
    attributeName="d"
    repeatCount="indefinite"
    dur="2s"
    to="           
        終了点のパス;" />
</path>
```

`attributeName`はアニメーション対象の属性名です。
今回はパスの形状をアニメーションさせたいため`d`を指定します。

`repeatCount` 属性はアニメーションの繰り返し回数を設定します。
今回は`indefinite`とし、無限に繰り返すようにします。

`dur`属性はアニメーションの期間を指定します。

`to`はアニメーションの終了点のパスを指定します。今回はBのSVGのパスを指定しました。
※Bの図形のSVGファイルを開き、`d=""`の値をコピペします。

```html
<path d="m69.26999,9.11177C29.43201,29.08436,3.2874,100.72029.26999,147.11177c-3.53709,54.38138,28.24796,75.68597,62,101,36,27,69,56,117,51,66.9773-6.9768,121-93.97767,121-146,0-34.70957-14.26495-70.8966-72-111C183.04258,10.69631,115.53699-14.08397,69.26999,9.11177Z"/>
```

# 2.SVGのパスをふわふわさせてみる

1で作成したアニメーションをループし、ふわふわした形に変更します。

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="dyaJoNa" data-user="fg_noguchi" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/fg_noguchi/pen/dyaJoNa">
  SVGのパスをふわふわさせてみる</a> by Noguchi (<a href="https://codepen.io/fg_noguchi">@fg_noguchi</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

`to`を`values`に変更し、パスを設定していきます。
`values`属性には、開始点と終了点のパスデータを指定します。

```html
<path d="開始点のパス">
<animate
    ・・・(略)・・・
    values="
        開始点のパス;              
        終了点のパス;
        開始点のパス;" />
</path>
```

今回は2つの図形のみ使用しましたが、`values`属性にはいくつも値が指定できるので、
途中時点のパスを指定することでより細かい動きを指定することもできます。

# 3.マウスオーバー時にふわふわさせてみる

次に、マウスオーバーさせた時にアニメーションを動作させ、マウスアウト時にアニメーションを停止させてみます。

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="WNPdvEo" data-user="fg_noguchi" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/fg_noguchi/pen/WNPdvEo">
  【HTMLでSVGモーフィング.3】マウスオーバー時にふわふわさせてみる</a> by Noguchi (<a href="https://codepen.io/fg_noguchi">@fg_noguchi</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

animateタグの属性に、下記を追記します。

```html
<animate
    ・・・(略)・・・
          begin="mouseover"
          end="mouseout"
    ・・・(略)・・・
 />
```

`begin`ではアニメーションが始まるタイミングを指定できます。
マウスオーバー時に実行させたいので`mouseover`を指定します。

`end`ではアニメーションを停止するタイミングを指定できます。
マウスオーバー時に停止させたいので`mouseout`を指定します。

`begin`と`end`には様々な値が設定でき、クリックなどのタイミング指定できます。

# まとめ

今回の記事を書くにあたり、animateタグには属性が指定できることを知りました。
ご紹介したのはそのごく一部になります。

複雑なアニメーションを実装したい場合はHTMLで実装するよりも、CSSやJavaScriptなどによって実装するほうが良いケースもありますが、簡単なアニメーションを実装したいのであればHTMLのみで十分かもしれません。
またデザインデータから抜き出したSVGパスも活用できるため、正確にデザインを反映しやすいこともメリットです。