SVGモーフィングでぬるっと変形するアニメーションを実装しよう!

どうも、最近時間を金で買う悦びをドラム式洗濯機から学んだ
フロントエンドエンジニアのいっちーです。

フロントエンド
エンジニア

いっちー

今回はお手軽かつサイトのアクセントにピッタリなWEBアニメーションをご紹介します。
よければご覧ください。

フロントエンド
エンジニア

いっちー

早速本題に入っていきますが、
みなさん、「モーフィング」ってご存知でしょうか?
なんかこう、一言で言うと「アハ体験」で使われる手法ですね。
マイケルジャクソンのMVでも使用されていたことで有名なようです。僕は知りませんでした。

モーフィングとは
コンピュータグラフィックスの手法の1つで、
ある画像から別の画像へ変化していく間をコンピュータによって補完することで自然に変形する映像を作成すること。

ちなみに恐縮ですが今回ご紹介するのはここまでハイレベルなものじゃないです。

フロントエンド
エンジニア

いっちー

今回はSVGを使用してモーフィングWEBアニメーションを実装していきます!
さっそく挑戦してみましょう!

SVGモーフィングアニメーションのつくり方

はじめに

今回の完成イメージです。
手順に沿ってもにゅもにょと形を変えながら伸び縮みする物体をつくっていきます。

2つのパスデータを用意

グラフィックを作成

Adobe XDの編集画面

まず初めに、作りたいモーフィングアニメーションをイメージして、「変化前」と「変化後」のグラフィックを作成します。
XDやillustratorなど、シェイプツールやペンツールでグラフィックが作成できるものであればどれを使用しても大丈夫です。
今回はXDを使用します。

▼ペンツールなどで「変化前」の図形を描いていきます。

次は「変化後」の図形を描いていきます。
ここで注意点ですが、アンカーポイント(頂点)の数は変化前後で一致させるようにしましょう。
オススメは「変化前」の図形のコピーをベースにすることです。アンカーポイントの数が一致しているか数えなくていいですし、より自然にモーフィングされるようアンカーポイントの移動先を意識して作成できます。

▼コピーして・・・

▼ハンドルを操作して形を変える。

これで「変化前」「変化後」の両方が完成しましたね。

SVGコードをコピー

出来上がったそれぞれの図形のSVGコードをコピー(パスに右クリック⇒「SVGコードのコピー」を選択)して控えておきましょう。
以下のようにsvgタグで囲まれているコードが取得できたと思いますが、
最終的にはfill属性がついていない方のpathタグの「d」の中身(M~~~Zの部分)だけ使用します。
これでひとまずパスデータの用意は完了です。

【変化前図形のSVGコード】
	<svg xmlns="http://www.w3.org/2000/svg" width="247.569" height="210.305" viewBox="0 0 247.569 210.305">
	  <g id="パス_1" data-name="パス 1" transform="translate(20.628 25.534)" fill="none">
		<path d="M67.649-22.691c65.079-15.957,132.882,38.3,155.224,86.621S170.4,190.189,122.594,184.474-31.2,161.612-19.772,90.948,2.57-6.734,67.649-22.691Z" stroke="none"/>
		<path d="M 91.43589019775391 ~~省略~~ -25.53413391113281 Z" stroke="none" fill="#000"/>
	  </g>
	</svg>


【変化後図形のSVGコード】
	<svg xmlns="http://www.w3.org/2000/svg" width="214.21" height="156.608" viewBox="0 0 214.21 156.608">
	  <g id="パス_2" data-name="パス 2" transform="translate(-22.495 13.53)" fill="none">
		<path d="M68.113-4.379c65.079-15.957,125.74-18.705,161.071,56.635s-63.909,88.329-88.849,89.888-88.849,5.715-103.4-33.773S3.033,11.578,68.113-4.379Z" stroke="none"/>
		<path d="M 130.7959289550781 ~~省略~~ -13.53005981445312 Z" stroke="none" fill="#000"/>
	  </g>
	</svg>

svgファイルにパスデータを記述

お次はテキストエディタに移ります。
以下のようにsvgテキストデータを用意してください。
durやrepeatCountなど、animate要素の属性はお好みで。

<svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 -50 300 300" width="400px" height="300px">
 <path>
  <animate
   attributeName="d"        //アニメーションする対象の属性名(パスを動かすので「d」としてください)
   dur="10s"                //アニメーション時間
   repeatCount="indefinite" //繰り返す回数(無限にしたいので「indefinite」としています)
   values="
     ---変化前のパスが入ります---;
     ---変化後のパスが入ります---;
     ---変化前のパスが入ります---
    ">
  </animate>
 </path>
</svg>

valuesの中には、控えておいたSVGコード内のパスデータを貼り付けましょう。
「d」の中身(M~~~Zの部分)がパスデータです。
A→B→Aと、1行目と最終行を必ず同じパスデータにすることがポイントです。
でないとモーフィングしなくなります。

カンマ忘れにも注意!

フロントエンド
エンジニア

いっちー

▼dの中身をvaluesの中にペースト。パス同士の間にセミコロンが付いているかもチェックしましょう。

   values="
     M67.649-22.691c65~~省略~~67.649-22.691Z;
     M68.113-4.379c65~~省略~~033,11.578,68.113-4.379Z;
     M67.649-22.691c65~~省略~~67.649-22.691Z
    ">

完成

パスデータを貼り付け終えたら、実際に動くか確認してみましょう。
このように滑らかに変形すれば成功です!
また、簡単なグラデーションであれば、defsタグ内にグラデーション用の記述をしておくだけで実現できます。

See the Pen
SVGモーフィング成功例
by IchidaTatsuhiro (@ichidatatsuhiro)
on CodePen.

失敗例①(頂点数が不一致)

作成までの道のりが見えたと思いますので、
ここからは失敗例を挙げながらいくつか注意点を解説していきます。

SVGモーフィングアニメーションをつくるにあたって
前述の通りアンカーポイントの数は必ず一致させる必要があります。
以下の例ではアンカーポイントの数が4:5になっていて一致していない状態です。
前後のパスデータに不整合があるとこのようにカクカクと図形が切り替わるだけになってしまいます。

See the Pen
SVGモーフィング失敗例①
by IchidaTatsuhiro (@ichidatatsuhiro)
on CodePen.

失敗例②(XDで発生)

図形を変形させたいときは、アンカーポイントから生えているハンドルをドラッグして操作しますよね。
ただしXDでは、

2箇所以上のアンカーポイントに対して
・ハンドルを折る(左右独立して動かせるようにする)
・ハンドルを消す(片方削除または両方削除)

のいずれかをおこなうと前後の図形で不整合が起きるのかモーフィングしなくなります。
ただし、変化前と変化後の図形両方とも元々同じアンカーポイントを折ったり消したりしている場合は辻褄が合うのか、成功しますので
あらかじめ複雑な図形を作成するつもりであれば変化前の図形の段階で折っておくといいと思います。
(そんなことするくらいならXD以外のツールで作成した方がいいじゃんと思いつつ、やむを得ない事情がある場合にぜひ)

See the Pen
SVGモーフィング失敗例②
by IchidaTatsuhiro (@ichidatatsuhiro)
on CodePen.

考察

ではなぜXDでこういった現象が起きるのでしょうか。

以下にXDとFigmaでそれぞれハンドルをいじくり倒したパスデータを載せました。
よく見るとXDで作成したパスデータにはSコマンドが混ざっていますね。
対してFigmaで作成したパスデータはCコマンドで統一されています

▼XDで作成したパスデータ

【変化前】
M67.649-22.691c65.079-15.957,132.882,38.3,155.224,86.621S170.4,190.189,122.594,184.474-31.2,161.612-19.772,90.948,2.57-6.734,67.649-22.691Z

【変化後】
M67.649-22.691c65.079-15.957,132.882,38.3,155.224,86.621s-100.28,120.544-100.28,120.544c-47.8-5.715-153.8-22.862-142.366-93.525S67.649,59.854,67.649-22.691Z

▼Figmaで作成したパスデータ

【変化前】
M197.186 26.0772C149.586 -23.9228 80.3526 12.2438 51.6859 36.5772C24.8526 53.0772 -20.5141 103.977 12.6859 175.577C54.1859 265.077 147.686 235.077 236.186 184.577C324.686 134.077 256.686 88.5771 197.186 26.0772Z

【変化後】
M246.372 60.1545C189 -51.5 86.4999 6.49998 148.686 130.077C33 67 -67 147.5 61.8719 209.654C26 309 204.5 397.5 285.372 218.654C417.5 234 439 79.5 246.372 60.1545Z

Figmaでつくった方はバキバキにハンドルを折っているのですが
このように生き生きとモーフィングしています。

See the Pen
SVGモーフィング考察用
by IchidaTatsuhiro (@ichidatatsuhiro)
on CodePen.

おそらくですが、
XDは滑らかに繋がったベジェ曲線を頑張ってSコマンドで表そうとしているため、
変化前後で座標の値が変わるだけで済むCコマンドのみでの表現と比べて破綻しやすいのではと推測されます。
コマンドについて興味のある方はMozillaの公式ウェブサイトをご覧ください。

MDN Web Docs:https://developer.mozilla.org/ja/docs/Web/SVG/Tutorial/Paths

 

そもそもXDは今回のテーマのような用途には向いていないのかもしれないですね。

フロントエンド
エンジニア

いっちー

惜しい例(見切れている)

モーフィングは成功してるものの一部見切れてしまっているケースです。
ダイナミックに変形させたいときによくあります。
例では横に伸びていった結果、先端部分が切れてしまっていますよね。

このようなケースで意図通りに表示されるようにしたい場合は、
svgタグのviewBox属性width属性height属性の値を調整することで解決します。
viewBoxの設定など詳しい解説は割愛しますが、修正後の例ではviewBoxのx座標を100px、widthを300pxに変更して見切れを解消しています。

▼修正前

See the Pen
SVGモーフィング惜しい例(修正前)
by IchidaTatsuhiro (@ichidatatsuhiro)
on CodePen.

▼修正後

See the Pen
SVGモーフィング惜しい例(修正後)
by IchidaTatsuhiro (@ichidatatsuhiro)
on CodePen.

応用編(3種類の図形に変化)

A⇒B⇒Aの順にパスを書いてモーフィングさせていましたが、
最初と最後が繋がっていれば大丈夫なのでA⇒B⇒C⇒Aなど間に他のパターンも追加できます。
よりバリエーション豊かな表現ができますね。

See the Pen
SVGモーフィング応用例
by IchidaTatsuhiro (@ichidatatsuhiro)
on CodePen.

おわりに

いかがでしたでしょうか?
複雑な処理を考える必要なく好きな形に変えられるSVGモーフィングアニメーション、
形状変化のみという制限があるものの使い方によってはグッと魅力が上がるサイトにできそうですよね。
これを機に、サイトのあしらいに利用してみてください!
多用しすぎるとページの読み込みが遅くなるのでその点だけご注意を。

ロジカルスタジオではフロントエンジニアを募集しています。
アニメーション実装が好きな方、モダンなウェブフロント技術を使って開発がしてみたいという方は、是非採用サイトからご応募ください!