【SMIL】SVGアニメーションでsvgのキャラ画像を動かそう!

この記事は最終更新から4年以上が経過しています。情報が古くなっている可能性があります。

前記事「【Illustrator】ラスタ画像からsvg画像を作る方法」に続いてsvg関連。
今度はsvgアニメーションを実装してみました。

svgアニメーションには、

  1. aminate要素(SMIL(スマイル))を用いる
  2. javascriptを用いる
  3. css3のアニメーションを用いる

この3つの方法があるそうです。

(1)に比べ、(2)、(3)のほうが高度なアニメーションが実装できるそうですが、今回は「わざわざjsやcssでアニメーションさせるほどじゃないけどちょっと動かしたいよね」という時に使える、SMILを用いたプチアニメをまとめました!

今回つくってみたもの

 

  • 目をぱちぱち(aminate要素 path変化)
  • ぴょんぴょんとジャンプ(animateTransform要素 並進(translate))
  • 耳をぱたぱた(animateTransform要素 回転(rotate))
  • (おまけ) ごろごろ回転移動(animateTransform要素 並進(translate), 回転(rotate))

下準備

全体に共通する方法として、まずアニメーションさせたいsvg画像を用意します。
*ラスタ画像をsvg画像化する方法については前記事で紹介しています。

次にsvg画像をブラウザ上で表示し、開発者ツールで動かしたい要素を特定します。

エディタでsvgのコードを開き、先ほど特定した動かしたい要素のタグを修正。

<!-- 修正前 -->
<path d="パスの中身"/>

<!-- 修正後 -->
<path d="パスの中身">
    <animate>
</path><!-- 閉じタグを追加して、中にanimate要素等をいれる -->

このタグの中にSMIL言語のアニメーションを実装する要素を記載していきます。
今回はanimate要素もしくはanimateTransform要素を使います。

SMIL…
W3CがXMLをもとに規格化したマークアップ言語。SMILを利用することで、動画や音声、テキストなどの異なる形式のデータを、Webブラウザー上で同期をとって再生できる。animate要素やanimateTransform要素はこの言語の技術。
引用元)SMIL(すまいる)とは – コトバンク
animate要素…
animate 要素は1個の属性/プロパティに対する時経過に伴うアニメーションに用いられる。
引用元)アニメーション – SVG 1.1 (第2版)
animateTransform要素…
animateTransform 要素は対象要素の変換属性に対するアニメーションを行い、それによる並進, 拡縮, 回転, 斜傾などを制御するアニメーションを可能にする。
引用元)アニメーション – SVG 1.1 (第2版)

目をぱちぱち

こちらの記事をがっつり参考にさせていただきました。
変化前と変化後のパスを用意し、ぬるっとアニメーションさせる方法です。

  1. svg画像aと、目だけ細く変更したsvg画像bを用意
    *このときアンカーの数を変えないように、とのこと。
  2. 画像bをブラウザで開き、どちらかの目の部分の要素を特定。Dから始まる文字列を控える
  3. 画像aをブラウザで開き、同じほうの目の部分の要素を特定。以下の形のコードに書き直す
<!-- 目のパスを特定 -->
<path fill="var(--color376, #201e18)" d="元のパス">
    <animate attributeType="XML" attributeName="d" dur="5s" repeatCount="indefinite" values="元のパス; 変化後のパス; 元のパス"></animate>
</path>

完成!
目をぱちぱちする間隔は秒数とvalueの数で無理やり調整してみました。

See the Pen NyNdzb by BICOxxx (@BICOxxx) on CodePen.

ぴょんぴょんとジャンプ

今度はanimateTransform要素で並進させてジャンプのように見せます。
先ほどの瞬きと同じように秒数とvalueの数でそれっぽい動きにしてます。

1.画像をブラウザで開き、体全体のpathを特定。もしグルーピングするgタグがなければgで囲う。

<g><!-- ←gタグを追加 -->
   <path fill="var(--color372, #fedc78)" d="Mxxx.xxx~"><!-- 体のパス -->
   <path fill="var(--color372, #fedc78)" d="Mxxx.xxx~"><!-- 鼻のパス -->
   <path fill="var(--color372, #fedc78)" d="Mxxx.xxx~"><!-- 目のパス -->
   ...(体を構成する全ての要素)
</g><!-- ←g閉じタグを追加 -->

2.このgタグの中に以下の形のコードを書き足す

<g>
    <path fill="var(--color372, #fedc78)" d="Mxxx.xxx~">
    <path fill="var(--color372, #fedc78)" d="Mxxx.xxx~">
    <path fill="var(--color372, #fedc78)" d="Mxxx.xxx~">
    <path fill="var(--color372, #fedc78)" d="Mxxx.xxx~">
  <animateTransform xmlns="http://www.w3.org/2000/svg" attributeName="transform" attributeType="xml" type="translate" dur="6s" values="0 0;0 0;0 -3;0 -5;0 -6;0 -5;0 -3;0 0;0 -3;0 -5;0 -6;0 -5;0 -3;0 0;0 0" keyTimes="0;0.5;0.51;0.52;0.53;0.54;0.55;0.56;0.57;0.58;0.59;0.60;0.61;0.62;1" repeatCount="indefinite"/><!-- animateTransformを追加 -->
</g>

完成!

See the Pen pig jumping by BICOxxx (@BICOxxx) on CodePen.

耳をぱたぱた

次はanimateTransform要素の回転を使います。
耳のpathに対してアニメーションをかけていきます。

    • 画像をブラウザで開き、耳のpathを特定。以下のコードに書き直す。
<!-- 左耳のパス -->
<path fill="var(--color374, #fec009)" d="Mxxx.xxx~">
	<animatetransform attributetype="XML" attributename="transform" type="rotate" values="0,10,5;30,10,5;0,10,5" dur="2s" repeatcount="indefinite" additive="sum"/>
</path>

<!-- 右耳のパス -->
<path fill="var(--color375, #fec109)" d="M28.021 3.233c.834-.138 1.613.104 2.379.378 1.739.62 3.328 1.504 4.696 2.758.203.187.39.384.563.593l.008.01c1.286 1.562.956 3.066-.864 3.967l-.348.172c-.66-1.123-1.266-2.279-2.053-3.323-1.213-1.607-2.556-3.087-4.169-4.306-.078-.074-.148-.155-.208-.244l-.003-.005z">
	<animatetransform attributetype="XML" attributename="transform" type="rotate" values="0,30,3;-30,30,3;0,30,3" dur="2s" repeatcount="indefinite" additive="sum"/>
</path>

完成!

See the Pen pig ear by BICOxxx (@BICOxxx) on CodePen.

ごろごろ回転移動

おまけ。animateTransform要素の並進と回転を合わせるとこんなこともできます。

See the Pen pig rolling by BICOxxx (@BICOxxx) on CodePen.

気になったところ

一定間隔を指定する方法

目の瞬きやジャンプを実装するときに調べましたが、「一定の時間をおいてアニメーションを実行」という命令はできなさそうです。

アナログで書くならこんな感じに。

<animate attributeType="XML" attributeName="d" dur="5s" repeatCount="indefinite" values="
	元のパス;元のパス;元のパス;元のパス;元のパス;元のパス;
	変化後のパス;
	元のパス;
	変化後のパス;
	元のパス;元のパス
"></animate>

これだと、durに指定した5秒間で、valueに指定したパスが等間隔で表示されるので近い挙動になります。
こういう細かい動きはcssやjsでの領域になるのかもしれませんね。

ease等の滑らかな動きの再現方法

こちらは名称を使った設定こそできませんが、cssでのeaseといった名称がついている設定値をkeySplines属性に使うことで再現可能だそうです。
詳細がこちらに記載されてました。

ease 0.25 0.1 0.25 1.0
linear 0.0 0.0 1.0 1.0
ease-in 0.42 0 1.0 1.0
ease-out 0.0 0.0 0.58 1.0
ease-in-out 0.42 0.0 0.58 1.0

引用元:svg要素の基本的な使い方まとめ > keySplines属性に設定する値について

まとめ

SMILはささやかなアニメーションであれば数行のコードで実装できるので、cssとjsとは違った用途に使えそうですね。
こちらの記事のような、がっつりとした変形アニメーションも面白そうです。

しかしこの記事を起こしてから知ったのですが、SMILは一度chromeで非推奨の動きがあったそうです。

chrome(blink)におけるSMILの非推奨警告の経緯

2015/7 chromeから非推奨の警告 公式記事

      • Chrome 45 Beta版からSMILは非推奨、将来的には機能自体非対応になると発表
      • SMILが設定されたSVGがページに表示されている場合、開発者ツールのコンソールに警告文を表示

2016/8 chromeから非推奨措置の保留

      • 反対意見が多かったこと、まだcssのアニメーションではSMILの代替として十分でないとの理由で方針の保留を発表

参考)#35:SVGアイコン管理ツール、SMILの今後についてなど

2018/1現在、特に新しい発表はないようです。
こういうことがあったため、chromeで現在SMILが使えない訳ではありませんが、SMILの将来性が不安視されるため、cssやjsを主に使おうという意見が多いようです。
(*なおIE11・EdgeはそもそもSMIL非対応)

IE, MS Edgeでは依然としてSMILは非対応ですし(参考:Can I use)、もしも今後の仕様追加でCSS/Web Animationsで十分に代替できるようになれば再びSMILの見直しがされる可能性があります。

そういった点を鑑みて、可能であればアニメーションを設定する際にはSMILではなくJavaScript, CSS/Web Animationsで制作するのをお勧めします。
#35:SVGアイコン管理ツール、SMILの今後についてなど

SVG要素の一つであるanimateタグを使う。
SMIL(Synchronized Multimedia Integration Language)というらしい。
今後ブラウザがサポートしていくかどうか決定していないので非推奨。
SVGのアニメーション手段とその選び方

今回のSMILアニメーションは知識として頭にいれておき、
今後SVGアニメーションを実装する際はSMILではなくcss、js中心で組んでいこうと思います。

参考サイト