SVG アニメーション(SMIL を使ったアニメーション)

SMIL を使った SVG アニメーションについての覚書です。animate 要素や animateMotion 要素、animateTransform 要素などのアニメーション要素の基本的な使い方について。

更新日:2021年02月24日

作成日:2021年2月18日

SVG アニメーション(SMIL)関連の仕様などの情報

SVG アニメーション(SMIL)関連の参考サイト

アニメーションに関する参考サイト

SVG の基本的な使い方については以下を御覧ください。

関連ページ:

SVG SMIL ブラウザの対応状況

can i use : SVG SMIL animation

アニメーションの方法

SVG のアニメーションは、SVG の図形要素のプロパティ(属性)を時系列的に変化させて実現します。SVG のアニメーションには大きく分けると以下のような方法があります。

  • CSS3 のアニメーションを利用
  • SVG DOM と JavaScript を利用
  • SVG の アニメーション要素(SMIL)を利用

SMIL は Synchronized Multimedia Integration Language(マルチメディア統合言語)の略称です。

参考:SVG 文書のアニメート法英語原文

以下はアウトライン(stroke)の stroke-dashoffset 属性の値を変化させるアニメーションを CSS、JavaScript、SVG(SMIL)で行う例です。

以下の例では同じ id を指定した div 及び path 要素を使用しているので、同じドキュメント内で試す際は id を変更する必要があります。

CSS を使ったアニメーション

以下は path 要素で作成した SVG のロゴ(の親要素の div 要素)にマウスオーバーしたら、CSS の animation を使ってアウトラインのアニメーションを実行する例です(Safari では機能しないようです)。

path 要素の d 属性の値は長いので途中省略しています。

HTML
<div id="svg_logo_wrapper">
  <svg width="300px" height="36px" viewBox="0 0 300 36">
    <path id="svg_logo" d="M273.593,34.680 ・・・中略・・・764,9.227 Z"/>
  </svg>
</div>

@keyframes で stroke-dashoffset の値を path の長さ(1237px)から0に変化させています。

path 要素にマウスオーバーしたらアニメーションを実行させることもできますが、この例の場合、path 要素の形状が複雑なのでマウスを少し動かすだけで hover が複数回発生してしまうため、親要素の div 要素に hover を設定しています。

CSS
#svg_logo {
  stroke: #000;
  stroke-width: 1px;
  fill: transparent;
}
#svg_logo_wrapper:hover {
  animation: dash_animation 2s ease-in both;
}
@keyframes dash_animation {
  0% {
  stroke-dashoffset:1237px;
  stroke-dasharray:1237px;
  }
  100% {
  stroke-dashoffset:0;
  }
}

以下は SVG のロゴ(の親要素の div 要素)にマウスオーバーしたら CSS の transition と JavaScript を使ってアウトラインのアニメーションを実行する例です。

この例では JavaScript を使って path の長さを取得して初期値に設定し、ホバー時に CSS の transition でアニメーションを実行しています。

HTML/JavaScript
<div id="svg_logo_wrapper" style="max-width: 300px;">
  <svg width="300px" height="36px" viewBox="0 0 300 36" onload="logo_animate()">
    <script><![CDATA[ 
      const logo_animate  = () => {
      // path 要素を取得
      let svg_logo = document.getElementById('svg_logo'); 
      //path の長さを取得(約 1237px)
      let svg_logo_length = svg_logo.getTotalLength(); 
      // path 要素の stroke-dashoffset と stroke-dasharray に値を設定
      svg_logo.style.setProperty('stroke-dashoffset', svg_logo_length);
      svg_logo.style.setProperty('stroke-dasharray', svg_logo_length);
        }
    ]]></script>
 
    <path id="svg_logo" d="M273.593,34.680 ・・・中略・・・764,9.227 Z"/>
  </svg>
</div>
CSS
#svg_logox {
  stroke: #000;
  stroke-width: 1px;
  fill: #eee;
  /* transition を設定 */ 
  transition: all 2s;
}
#svg_logo_wrapperx:hover #svg_logox{
  /*ホバー時に  を0に(!important を指定)*/ 
  stroke-dashoffset: 0 !important;
}

CSS3 の animation プロパティtransition プロパティで SVG の属性使ってアニメーションが行えます。

CSS を使った SVG 要素のアニメーションは、HTML 要素を使うアニメーションと同じように機能します。

CSS のアニメーションでもいろいろなことができますが、全ての属性が CSS で設定できるわけではなく、例えば個々の図形要素の座標(x、y、cx、cy)やサイズ(width、height、r)、パスの情報(d)など、属性によっては CSS で設定できないものがあります。

また、transform 属性は CSS と SVG では変形の基点 transform-origin の初期値が異なっています。

  • CSS の transform-origin の初期値:50% 50%
  • SVG の transform-origin の初期値:0 0

JavaScript を使ったアニメーション

以下は JavaScript を使って、ページの読み込み時と SVG ロゴの親要素の div 要素をクリックしたらアウトラインのアニメーションを実行する例です。※ Web Animation API の animate() メソッドを使用しているため、現時点(2021年2月)では Safari などでは機能しません。

HTML(前述の CSS の例と同じ)
<div id="svg_logo_wrapper">
  <svg width="300px" height="36px" viewBox="0 0 300 36">
    <path id="svg_logo" d="M273.593,34.680 ・・・中略・・・764,9.227 Z"/>
  </svg>
</div>

CSS では最初に表示されるスタイルを設定しています。

CSS
#svg_logo {
  stroke: #000;
  stroke-width: 1px;
  fill: transparent;
}

path の長さを getTotalLength() で取得して、Web Animation API の animate() メソッドで stroke-dashoffset の値を変化させています(CSS の @keyframes とほぼ同じ内容)。

JavaScript
<script>
  let svg_logo = document.getElementById("svg_logo");
  //path の長さを取得(約 1237px)
  let svg_logo_length = svg_logo.getTotalLength(); 
  //アニメーションを定義して実行(読み込み時に一度実行される)
  let svg_logo_anime = svg_logo.animate(
    [
      { strokeDashoffset:svg_logo_length, 
        strokeDasharray:svg_logo_length, 
        easing: "ease-in-out"},
      {strokeDashoffset:"0"}
    ], {
    duration: 2000
  })
  let svg_logo_wrapper = document.getElementById("svg_logo_wrapper");
  //クリックイベントのリスナーの登録
  svg_logo_wrapper.addEventListener("click", () => {
    //定義したアニメーションを実行
    svg_logo_anime.play();
  });
</script>

以下は jQuery の animate() メソッドを使って SVG ロゴの親要素の div 要素をクリックしたらアウトラインのアニメーションを実行する例です。こちらの方法だと Safari でも機能します。

JavaScript
jQuery(function($){
  //path の長さを取得(約 1237px)
  let svg_logo_length = document.getElementById("svg_logo").getTotalLength();
  //クリックイベント
  $("#svg_logo_wrapper").click(function() {
    $("#svg_logo").not(":animated").css({
      //stroke-dashoffset と stroke-dasharray に path の長さを設定
      strokeDashoffset: svg_logo_length, 
      strokeDasharray: svg_logo_length
    }).animate({
      //stroke-dashoffset を 0 に
      strokeDasharray:"none" ,
      strokeDashoffset:"0"  
    }, 2000, "swing"); 
  }); 
});

JavaScript で DOM を操作することで CSS ではできないこともアニメーション化が可能です。

JavaScript を使った SVG アニメーションでは、SMIL や CSS を使う場合と同様(またはそれ以上)の機能を得ることができます。CSS や SMIL のアニメーションで制約されている多くのことが JavaScript では対応可能となっているようです。

但し、img 要素や picture 要素、CSS background-image を使って取り込んだ SVG は JavaScript を使ってアニメーションすることができません(セキュリティの点からスクリプトが動作しません)。

また、Greensock(GSAP)などのライブラリを使用すればクロスブラウザに対応できたり、実装(コードの記述)も簡単になります。

SMIL を使ったアニメーション

以下は SVG の animate 要素を使って、SVG ロゴ(path 要素)をクリックしたらアウトラインのアニメーションを実行する例です。

この例では animate 要素はアニメーションを実行する path 要素の中に記述し、stroke-dasharray の初期値を path 要素に指定しています。

また、プレゼンテーション属性を使って stroke や fill などを設定しています(別途 CSS で stroke や fill のスタイルを設定することも可能です)。

HTML
<div class="logo_wrapper">
  <svg width="300px" height="36px" viewBox="0 0 300 36">
    <path id="svg_logo" 
      stroke-dasharray="1237" 
      stroke="#000" 
      stroke-width="1" 
      fill="transparent" 
      d="M273.593,34.680 ・・・中略・・・764,9.227 Z"> 
      <!--SVG のアニメーション要素-->
      <animate 
        attributeName="stroke-dashoffset" 
        from="1237px" 
        to="0" 
        dur="5s" 
        repeatCount="1" 
        begin="click"
      />
    </path>
  </svg>
</div>

以下は上記の例とほぼ同じですが、JavaScript を使って path の長さを取得して path 要素の stroke-dasharray 属性や animation 要素の from 属性の値を設定する例です。この方法では path の長さを調べる必要がありません。

この例では svg 要素に onload イベント属性を設定して JavaScript を呼び出しています。(参考:SVG 1.1 スクリプト

また、この例では begin 属性に mouseover を指定してマウスオーバー時にアニメーションを実行しています。但し、path の形状が複雑なので restart 属性に whenNotActive を指定してアニメーションが実行中は再度アニメーションが発生しないようにしています(この例の場合、アニメーション実行後5秒たたないとアニメーションは再度実行されません)。

<div class="logo_wrapper">
  <svg width="300px" height="36px" viewBox="0 0 300 36" onload="logo_init()">
    <script><![CDATA[ 
      const logo_init  = () => {
        let svg_logo = document.getElementById('svg_logo'); 
        let svg_logo_length = svg_logo.getTotalLength();  
        svg_logo.style.setProperty('stroke-dasharray', svg_logo_length);
        let logo_anim = document.getElementById('logo_anim');  
        logo_anim.setAttribute('from', svg_logo_length); 
      }
    ]]></script> 
    <path id="svg_logo" 
      stroke="#000"  
      stroke-width="1" 
      fill="transparent"
      d="M273.593,34.680 ・・・中略・・・764,9.227 Z"> 
      <animate id="logo_anim" 
        attributeName="stroke-dashoffset" 
        to="0" 
        dur="5s" 
        repeatCount="1" 
        begin="mouseover" 
        restart="whenNotActive"
      />
    </path>
  </svg>
</div>

以下は script タグの中で window.onload で設定する場合の例です。

<div class="logo_wrapper">
  <svg width="300px" height="36px" viewBox="0 0 300 36">
    <script><![CDATA[ 
      window.onload  = () => {
        ・・・中略・・・
      }
    ]]></script> 
    <path id="svg_logo" 
      ・・・中略・・・
      />
    </path>
  </svg>
</div>

SVG は SMIL(Synchronized Multimedia Integration Language) というマルチメディア記述言語のアニメーションの仕様で定義されている機能を組み込み、いくつかの SVG 特有の拡張(animateTransform 要素など)を提供しています。

SMIL を使えば、HTML のコードだけでアニメーションが可能で簡潔にコードを記述することができ、CSS ではできない属性の変更やモーフィング、パスに沿ったアニメーションが可能です(※ 使用する属性によってはブラウザごとのサポートが異なるものもあるようです)。

Chrome では2015年に SMIL を非推奨とする動きもあったようですが、その後(2016年)には撤回されているようです(stackoverflow.com/Is SMIL for SVG deprecated...?)。

SVG のアニメーション(CSS、JavaScript、SMIL の違いなど)については少し古い記事(2015年)ですが「SVGアニメーションの現状」が参考になりました。

SMIL の基本的な使い方

SMIL を用いた SVG のアニメーションでは主に以下のようなアニメーション要素を使います。

アニメーション要素(参考:SVG 1.1 仕様 SMIL アニメーションとの関係
要素 説明
animate 対象となる要素の属性(プロパティ)の時系列的な変化を指定してアニメーションを定義する要素。図形要素が持つほとんどの属性を制御できます。
animateMotion 要素をモーションパスに沿って動かすための要素(要素がモーションパスに沿って移動する方法を定義)。
animateTransform 変形アニメーションを定義する要素(SVG 特有の拡張)。
set 指定された期間の属性の値を設定する要素。数値ではない(文字列や論理型の)値を属性やプロパティに割り当てるのに使用できます。
animateColor 非推奨(現在は使えません。animate 要素で代用可能)

アニメーション要素は用途に応じて使い分け、以下のような属性を設定できます。

アニメーション属性
属性 説明
対象になる要素を特定する属性
xlink:href アニメーションの対象となる要素への参照を指定
対象になる属性(プロパティ)を特定する属性
attributeName 対象となる属性の名前を指定
attributeType 対象属性とその値が定義される名前空間を指定
タイミングを制御する属性
begin アニメーション開始のタイミングを定義。 click などのイベントや秒数を指定することができ、複数の値をセミコロン区切りで設定可能。
end アニメーションを終了するタイミングを定義。複数の値をセミコロン区切りで設定可能
dur アニメーションの持続時間を指定
min アニメーションの持続時間の最小値を指定
max アニメーションの持続時間の最大値を指定
repeatCount アニメーション関数の繰り返し回数を指定(数値 | "indefinite")。指定しなければ1回。
repeatDur 反復の全持続時間を指定
restart アニメーションの再開を可能にする条件を指定(always | whenNotActive | never)
fill アニメーション終了後に要素を初期状態に戻すかどうかを指定(freeze | remove)
時経過に伴うアニメーション値を定義する属性
from アニメーションの初期値を指定
to アニメーションの終了値を指定
by アニメーションの差分値(終了時の増減値)を指定
values 変化させる値のリスト(セミコロン区切り)を指定
calcMode アニメーションの補間モードを指定(discrete | linear | paced | spline)
keyTimes 値の変化が起こるタイミングのリスト(セミコロン区切り)を指定。アニメーション開始(0)から終了(1)までの割合で指定
keySplines keyTimes における各時区間に対する値の変化を3次ベジェ関数のリストを定義。x1 y1 x2 y2 の組をセミコロンで区切って指定(x1〜y2 の値は0〜1の間)。
アニメーション設定値を制御する属性
additive アニメーションが加法的(additive)であるかどうかを指定(replace | sum)
accumulate アニメーションが累積的(cumulative)であるかどうかを指定(none | sum)

animateMotion 要素では上記のアニメーション属性に加えて以下の属性を指定できます。

animateMotion 要素の専用属性
属性 説明
path モーションパスを定義する属性。
keyPoints 対応する keyTimes 属性で指定された値による時刻において、モーションパスに沿って対象の要素をどれだけ動かすかを指定。
rotate 図形の回転角を指定(数値 | auto | auto-reverse)既定値は 0

animateTransform 要素では上記のアニメーション属性に加えて以下の属性を指定できます。

animateTransform 要素の専用属性
属性 説明
type アニメーションで適用する変形の種類を指定。(translate|scale|rotate|skewX|skewY)

対象となる属性を特定

attributeName 属性と attributeType属性は時経過に伴って値が変化する対象となる属性(プロパティ)を特定します。

attributeName

attributeName には対象となる属性(プロパティ)を1つだけ指定することができます。複数の属性をアニメーションの対象とするには、別のアニメーション要素を設定します。

以下は円の半径の大きさ(r)と塗り(fill)の2つの属性を対象とするアニメーションで、円をクリックすると半径が 10 から 50 に、塗り色が水色(lightblue)からピンク(pink)に変わります。

2つの animation 要素それぞれに attributeName で対象の属性(r と fill)を指定しています。

<svg width="100px" height="100px" viewBox="100 100">
  <circle cx="50" cy="50" r="10" fill="lightblue">
    <!-- 円の半径(r 属性)を対象とするアニメーション -->
    <animate
      attributeType="XML" 
      attributeName="r"
      dur="1s" 
      from="10" 
      to="50"
      begin="click"/>
    <!-- 塗り(fill 属性)を対象とするアニメーション -->
    <animate
      attributeType="XML" 
      attributeName="fill"
      dur="1s" 
      from="lightblue" 
      to="pink"
      begin="click"/>
  </circle>
</svg> 

円をクリックするとアニメーションが開始します。

attributeType

attributeType を使ってアニメーション対象の属性の種類(その属性値が定義される名前空間)を指定することができ、以下の値が指定可能です。

  • XML:図形要素自体の属性(attributeName の値が XML 属性名であることを指示)
  • CSS:CSS 属性(attributeName の値が CSS プロパティ名であることを指示)
  • auto:自動判定(デフォルト)。

attributeType を設定していないか、auto に設定されている場合は、ブラウザーは最初に CSS プロパティのリストで一致するプロパティ名を検索し、見つからない場合は、デフォルトの XML 名前空間で要素を検索します。

以下は長方形の不透明度(opacity)を使ったアニメーションの例です。opacity 属性は CSS プロパティとしても使用できるため attributeType を CSS 名前空間に設定しています。

<svg width="120px" height="80px" viewBox="120 80">
  <rect x="0" y="0" width="120" height="80" rx="10" ry="10" fill="gold">
    <animate
      attributeType="CSS" 
      attributeName="opacity"
      dur="5s" 
      from="1" 
      to="0.1"
      repeatCount="indefinite"/>
  </rect>
</svg> 

animate 要素

animate 要素はアニメーションを定義する基本となる要素で、一度に1つの属性をアニメーション化するために使用されます(複数の属性をアニメーション化する場合は、それぞれの属性に対して animate などのアニメーション要素を使います)。

animate 要素は図形要素が持つ大部分の属性を制御でき、 数値や色の値をとる属性を使ってアニメーションを定義することができます。

from、to、 dur 属性

基本的なアニメーションである一定期間にわたって値を別の値に変更するために、from、to、及び dur 属性を使用することができます。

  • from:アニメーションの初期値を指定
  • to:アニメーションの終了値を指定
  • dur:アニメーションの持続時間を指定

from 及び to 属性は、CSS animation の @keyframe での from と to に対応していて、dur は CSS animation の animation-duration プロパティに対応していると捉えることができます。

また、begin 属性でアニメーションを開始するタイミングを指定でき、fill 属性でアニメーション終了後に要素を初期状態に戻すかどうかを指定できます。

以下の例では、円(circle)を定義し、その子要素として animate 要素を定義して円のアニメーションを呼び出しています。rect 要素は背景として配置しています。

attributeName に指定した円の中心(rx)は、from で指定した初期位置 50 からx軸に沿って to で指定した 250 に、dur で指定した 2s(2秒間)で移動します。

begin 属性には click を指定しているので、円をクリックするとアニメーションが開始されます。そして fill 属性に freeze を指定してアニメーション終了時の状態のままにしています(何も指定しないか remove を指定すると初期状態に戻ります)。

<svg width="300px" height="100px" viewBox="0 0 300 100">
  <rect x="0" y="0" width="300" height="100" fill="darkseagreen" />
  <circle r="30" cx="50" cy="50" fill="pink">
    <animate 
      attributeName="cx"
      from="50"
      to="250" 
      dur="2s"
      begin="click"
      fill="freeze" />
  </circle>
</svg>    

円をクリックするとアニメーションが開始します。

以下は polygon 要素の points 属性の値を from と to で指定してアニメーションさせる例です。このようなアニメーションの場合、from と to に指定する頂点の数を同じにする必要があります。

<svg width="120px" height="120px" viewBox="0 0 120 120">
  <polygon points="25,0 95,0 120,50 95,100 25,100 0,50" fill="mediumpurple">
    <animate 
      attributeName="points" 
      from="25,0 75,0 100,50 75,100 25,100 0,50" 
      to="119,78 0,82 33,96 120,1 0,1 81,99" 
      dur="3s"
      begin="click" 
      fill="freeze"/>
    </polygon>
</svg>

図形をクリックするとアニメーションが開始します。

以下は path 要素の d 属性の値を from と to で指定してアニメーションさせる例です。

※ path 要素のアニメーション(モーフィング)の場合、パスシェイプ(d 要素の値)が正確に同じ数の頂点/ポイントを持ち、同じコマンド及び順序で記述される必要があります。

<svg width="165px" height="155px" viewBox="0 0 165 155">
  <path stroke="cornflowerblue" stroke-width="5" fill="transparent" d="M10 0 L30 100 L120 20 L160 140">
    <animate 
     attributeName="d" 
     from="M10 0 L30 100 L120 20 L160 140" 
     to="M0 50 L100 80 L50 150 L10 30" 
     dur="4s"
     begin="click" 
     fill="freeze"/>
  </path>
</svg>

線をクリックするとアニメーションが開始します。

タイミングを制御する属性

begin 属性

begin 属性はアニメーション開始のタイミングを定義する属性で開始までの時間(秒数等)や click などのイベントを指定することができます。また、セミコロン区切りで複数の値を指定することができます。

上記の例では、begin の値に click を指定しましたが、値に秒数を設定することもできます。例えば、"0s" を指定すると、ページが読み込まれるとすぐにアニメーションを開始します。

正の時間値を設定することにより、アニメーションを遅らせることができます。"2s" を指定するとロードの2秒後にアニメーションを開始します。

負の値も指定することができます。負の時間値を設定すると、すでに過去にアニメーションを開始していたように動作します。

以下の例ではドキュメントをリロードすると、 1つ目のピンク色の円はすぐにアニメーションを開始し、2つ目の薄緑色の円は2秒後にアニメーションを開始します。3つ目の水色の円は負の値 begin="-2s" を指定しているので、開始から2秒後の位置からアニメーションを開始します。

<svg width="300px" height="100px" viewBox="0 0 300 100">
  <circle r="10" cx="10" cy="10" fill="pink">
    <animate 
      attributeName="cx"
      from="10"
      to="290" 
      dur="6s"
      begin="0s"
      repeatCount="indefinite" />
  </circle>
  <circle r="10" cx="10" cy="40" fill="lightgreen">
    <animate 
      attributeName="cx"
      from="10"
      to="290" 
      dur="6s"
      begin="2s"
      repeatCount="indefinite" />
  </circle>
  <circle r="10" cx="10" cy="70" fill="lightblue">
    <animate 
      attributeName="cx"
      from="10"
      to="290" 
      dur="6s"
      begin="-2s"
      repeatCount="indefinite" />
  </circle>
</svg> 

"click + 1s " と指定すればその要素がクリックされてから1秒後にアニメーションが開始されます。

複数の値も指定できるので、"click; 5s" と指定すれば、クリックするか、またはページを読み込んでから5秒後にアニメーションが開始されます。

<svg width="300px" height="40px" viewBox="0 0 300 40">
  <circle r="20" cx="20" cy="20" fill="red">
    <animate 
      attributeName="cx"
      from="20"
      to="280" 
      dur="1s"
      begin="click + 1s" />
  </circle>
</svg>

また、他の要素のイベントをトリガとしてアニメーションを開始することもできます(要素のイベントをトリガとしてアニメーションを実行)。

他のアニメーションと同期を取ることもできます(アニメーションに名前を付けて同期)。

fill 属性

fill 属性(SVG の塗りの属性と同じ名前ですが異なる属性)ではアニメーションが終了した後に要素を初期状態に戻すかどうかを指定することができ、次の値を指定することができます。

  • freeze:アニメーションの期間の最後の状態で効果の値をフリーズ(再開されるまで終了時の状態のまま凍結)します。
  • remove:(初期値)アニメーションの期間が終了するとアニメーション効果は削除され、元の状態に戻ります。

fill 属性は CSS animation の animation-fill-mode に該当します(指定できる値は異なりますが)。

by 属性

by 属性は、アニメーションの相対オフセット(差分)を指定するために使用されます。この属性を使用して、アニメーションを進行させる量を指定できます。

前述の例の場合、アニメーションの差分の値を指定する by 属性を使って以下のように書き換えても同じ結果になります(50 から 250 まで移動させるのでその差分 200 を指定)。

<!--to="250" の代わりに by="200" を指定 -->
<animate 
  attributeName="cx"
  from="50"
  by="200" 
  dur="2s"
  begin="click"
  fill="freeze" />
restart 属性

restart 属性はアニメーションの再開を可能にする条件を指定します。

この属性を使うとアニメーションがアクティブなときに再開されないようにするすることができます。この属性は、次の3つの値のいずれかに設定できます。

  • always:(初期値)アニメーションはいつでも再開できます。
  • whenNotActive:アニメーションはアクティブでない場合(つまり終了後)にのみ再開できます。 アクティブな期間中にアニメーションを再開する試みは無視されます。
  • never:(SVG ドキュメントフラグメントの)残りの期間(ページを再読み込みするまで)はアニメーションを再開できません。

以下は restart="never" を指定した例です。

一度クリックしたら、ページを再読み込みするまではアニメーションを再開できません。但し、現時点では Safari の場合、この指定は restart="whenNotActive" を指定したのと同じになるようです。

<svg width="200px" height="40px" viewBox="0 0 200 40">
  <circle r="20" cx="20" cy="20" fill="blue">
    <animate 
      attributeName="cx"
      from="20"
      to="180" 
      dur="3s"
      restart="never"
      begin="click" />
  </circle>
</svg>
repeatCount 属性

repeatCount 属性はアニメーションの繰り返し回数を指定する属性で0以上の数値を指定でき、指定しない場合は1回実行されます。indefinite を指定すると無限に繰り返します。

repeatDur 属性

アニメーションが長時間繰り返されると、煩わしかったり使い勝手が悪くなる場合があります。

repeatDur 属性はアニメーションを繰り返す時間を指定する属性で、時間または indefinite(繰り返しを継続)を指定できます。

指定する時間はドキュメント開始からの経過時間になり、5秒後であれば "5s"、1分30秒後であれば "01:30" のように指定できます。

以下の例の場合、ドキュメントが読み込まれてから円の図形はアニメーションを2回繰り返し、正方形の図形は9秒間繰り返し、三角形の図形は11秒間繰り返し、fill="freeze" を指定しているのでその位置で終了します。

三角形の図形のアニメーションは attributeName="points" を指定して、各頂点の x 座標を変化させています。

<svg width="300" height="300" viewBox="0 0 300 300">
  <circle id="circ1" r="30" cx="30" cy="30" fill="mediumpurple" />
  <rect id="rect1" width="60" height="60" x="0" y="80" fill="lightseagreen"/>
  <polygon id="polyg1"  points="0,220 30,160 60,220" fill="gold"/>
  <animate 
     xlink:href="#circ1"
     attributeName="cx"
     from="30"
     to="270" 
     dur="2s"
     begin="0s"
     repeatCount="2"
     fill="freeze"/>
  <animate 
     xlink:href="#rect1"
     attributeName="x" 
     from="0"
     to="240" 
     dur="2.5s"
     begin="0s"
     repeatCount="indefinite"
     repeatDur="9s" 
     fill="freeze"/>
  <animate 
     xlink:href="#polyg1"
     attributeName="points" 
     from="0,220 30,160 60,220"
     to="240,220 270,160 300,220" 
     dur="5s"
     begin="0s"
     repeatCount="indefinite"
     repeatDur="00:11"
     fill="freeze"/>
</svg>

ページを再読込するとアニメーションが再開されます。

end 属性

end 属性はアニメーションを終了するタイミングを定義する属性です。

begin 属性と同じように、click などのイベントや秒数を指定することができ、複数の値をセミコロン区切りで指定できます。

以下は図形をクリックした1秒後かドキュメントを開いていから10秒後にアニメーションが終了します。

<svg width="300" height="60" viewBox="0 0 300 60">
  <circle r="30" cx="30" cy="30" fill="pink">
    <animate 
      attributeName="cx"
      from="30"
      to="270" 
      dur="5s"
      begin="0s"
      end="click + 1s; 10s;"
      repeatCount="indefinite"
      fill="freeze"/>
  </circle>
</svg>

アニメーションを再開するにはページを再読込します。

要素のイベントをトリガとして実行

begin 属性に他の要素のイベント(要素のid.イベント名)を指定して、それをトリガとしてアニメーションを開始することもできます(要素のid を省略した場合は、その要素自身がアニメーションの対象)。

以下は長方形の図形をクリックしたら1秒後に円のアニメーションを開始する例です。

この例の場合、長方形の要素(rect 要素)の上に文字(Click!)を表示する text 要素を重ねているので、下にある rect 要素にイベントを伝えるため pointer-events="none" という属性を指定しています。

また、文字を水平方向中央揃えにするために、text 要素の x 属性を 50% に指定し、text-anchor 属性の値を middle に設定し、rect 要素にはプレゼンテーション属性として cursor="pointer" を設定しています。

<svg width="200px" height="200px" viewBox="0 0 200 200">
  <circle cx="100" cy="100" fill="red">
    <animate 
      attributeName="r" 
      begin="blue_rect.click + 1s" 
      dur="5s" 
      from="0" 
      to="100"/>
  </circle>
  <rect id="blue_rect" x="0" y="160" width="200" height="40" fill="blue" opacity="0.5" cursor="pointer"/>
  <text x="50%" y="190" font-size="20" fill="white" text-anchor="middle" pointer-events="none">Click!</text>
</svg>
Click!

begin 属性には複数の値をセミコロン区切りで指定できるので、以下のように text 要素に pointer-events="none" は設定せず、id を指定して begin 属性に追加することもできます。

<svg width="200px" height="200px" viewBox="0 0 200 200">
  <circle cx="100" cy="100" fill="red">
    <animate 
      attributeName="r" 
      begin="blue_rect.click + 1s; click_text.click + 1s" 
      dur="5s" 
      from="0" 
      to="100"/>
  </circle>
  <rect id="blue_rect" x="0" y="0" width="200" height="40" fill="blue" opacity="0.5" cursor="pointer"/>
  <text id="click_text" x="50%" y="30" font-size="20" fill="white" text-anchor="middle" cursor="pointer">Click!</text>
</svg>

アニメーションに名前を付けて同期

2つ以上のアニメーションがある場合(同じ要素に適用されているかどうかに関係なく)、 begin や end 属性を使って一方が他方に対して開始するように同期させることができます。

この方法では対象のアニメーションの期間を知らなくても実行することができます。対象のアニメーションを特定するために各アニメーションに ID を指定します。

以下の例では円をクリックすると円の移動のアニメーションが開始され、2秒後に正方形のアニメーションが、円の移動のアニメーションが終了すると円の塗の色が変わるアニメーションが開始されます。

1つ目の animate 要素(id="circ-anim")は円を移動するアニメーションで、begin="click" を指定しているのでクリックすると移動のアニメーションが開始されます。

2つ目の animate 要素(id="rect-anim")には begin="circ-anim.begin + 2s" を指定しているので、円を移動するアニメーションが開始されてから2秒後にアニメーションが開始されます。

3つ目の animate 要素(id="circ-anim2")には、begin="circ-anim.end + 1s" が指定してあり、円の移動アニメーションが終了してから1秒後に円の塗り色を変えるアニメーションが開始されます。

begin="circ-anim.end - 3s" のように指定すれば、円のアニメーションが終了する前に開始することもできます。

<svg width="300" height="150" viewBox="0 0 300 150">
  <circle id="circ" r="30" cx="30" cy="30" fill="mediumpurple" />
  <rect id="rect" width="60" height="60" x="0" y="80" fill="lightseagreen"/>
  <animate 
     xlink:href="#circ"
     attributeName="cx"
     from="30"
     to="270" 
     dur="2s"
     begin="click"
     repeatCount="2"
     fill="freeze"
     id="circ-anim"/>
  <animate 
     xlink:href="#rect"
     attributeName="x" 
     from="0"
     to="240" 
     dur="2.5s"
     begin="circ-anim.begin + 2s"
     repeatCount="indefinite"
     repeatDur="5s" 
     fill="freeze"
     id="rect-anim"/> 
  <animate 
     xlink:href="#circ"
     attributeName="fill" 
     from="mediumpurple"
     to="pink" 
     dur="3s"
     begin="circ-anim.end + 1s"
     repeatCount="indefinite"
     repeatDur="6s" 
     fill="freeze"
     id="circ-anim2"/>
</svg>

円をクリックするとアニメーションが開始します。

繰り返し回数に基づいてアニメーションを同期

あるアニメーションが別のアニメーションの繰り返し回数に基づいて開始するように同期することができます。但し、現時点では Chrome 以外(Firefox や Safari)では機能しないようです。

例えば、別のアニメーションのn回目の繰り返しの後にアニメーションを開始することができ、必要であればプラスまたはマイナスの時間を追加で指定することができます。

以下の例では、2つ目の animate 要素に begin="circ-anim.repeat(2)+0.5s" と設定しているので、円のアニメーションの2回目の繰り返しの終了後0.5秒で長方形のアニメーションを開始します。

<svg width="300" height="150" viewBox="0 0 300 150">
  <circle id="circ" r="30" cx="30" cy="30" fill="gold" />
  <rect id="rect" width="60" height="60" x="0" y="80" fill="lightgreen"/>
  <animate 
    xlink:href="#circ"
    attributeName="cx"
    from="30"
    to="270" 
    dur="2s"
    begin="click"
    repeatCount="4"
    fill="freeze"
    id="circ-anim"/>
  <animate 
    xlink:href="#rect"
    attributeName="x" 
    from="0"
    to="240" 
    dur="2.5s"
    begin="circ-anim.repeat(2)+0.5s" 
    repeatCount="indefinite"
    repeatDur="7.5s" 
    fill="freeze"
    id="rect-anim"/> 
</svg>

円をクリックするとアニメーションが開始します。

以下は円を移動するアニメーションの繰り返しごとに、円の色を変化させる例です(Safari では機能しないようです)。

この例では、set 要素を使って begin 属性をそれぞれ移動アニメーション(id が repeat_animation1)の開始時、1回目の繰り返し時、2回目の繰り返し時に設定して円の色を変更しています。

set 要素は開始トリガーを受けると to 属性の値をアニメーション対象の属性に設定します(一部の属性が指定できないことを除き、使い方は animate 要素と同じです)。

また、animate 要素では繰り返しを repeatCount 属性で3回と設定し、begin 属性で repeat_animation1.end と設定して自身の終了後、再開するようにしています。

<svg width="200px" height="50px" viewBox="0 0 200 50">      
  <circle cx="20" cy="20" r="20" fill="pink">
    <animate id="repeat_animation1" 
             repeatCount="3"
             attributeName="cx"
             from="20"
             to="180" 
             dur="2s" 
             begin="0s; repeat_animation1.end" />

    <set attributeName="fill"
         begin="repeat_animation1.begin" 
         to="pink" />

    <set attributeName="fill"
         begin="repeat_animation1.repeat(1)" 
         to="purple" />

    <set attributeName="fill"
         begin="repeat_animation1.repeat(2)" 
         to="lightblue" />
  </circle>   
</svg>

キーフレームアニメーション

from と to(初期値と終了値)だけではなく、複数の経過点を指定したキーフレームアニメーションも作成することができます。

values 属性

キーフレームアニメーションを作成するには、from と to または by の代わりに values 属性を使います。 values 属性には各時点での値をセミコロン区切りで指定します。

以下はアニメーションの対象を円の中心座標(cx)として、values 属性に "20; 280; 100; 200; 150"を指定して3秒間で cx の値を 20 → 280 → 100 → 200 → 150 に変化させるアニメーションです。

<svg width="300" height="80" viewBox="0 0 300 80">
  <rect width="300" height="80" x="0" y="0" fill="blue" opacity="0.1"/>
  <circle r="20" cx="20" cy="40" fill="red">
    <animate 
      attributeName="cx"
      values="20; 280; 100; 200; 150" 
      dur="3s"
      begin="click"
      fill="freeze"/>
  </circle>
</svg>

円をクリックするとアニメーションが開始します。

以下はアニメーションの対象を path 要素の d 属性として、各キーフレーム(values 属性)の値としてそれぞれの時点でのパス定義を指定して、徐々に形状が変化するアニメーションを作成する例です。

※ path 要素のアニメーション(モーフィング)の場合、パスシェイプ(d 要素の値)が正確に同じ数の頂点/ポイントを持ち、同じコマンド及び順序で記述される必要があります。

<svg width="100" height="100" viewBox="0 0 100 100">
  <path fill="#1F66E1">
    <animate
      attributeName="d"
      dur="8s" 
      repeatCount="indefinite"
      values="M 0,0 L50,0 L100,0 L50,100;
              M 0,100 L50,0 L100,100 L50,100;
              M 0,100 L50,0 L100,100 L50,0;
              M 0,0 L50,0 L100,0 L50,100" />
  </path>
</svg>

以下も path 要素のアニメーション(モーフィング)の例ですが、クリックすると色が変わるアニメーションも追加しています(values 属性に指定したパスの形状は calcMode 属性に discrete を指定すると簡単に確認できます) 。

<svg width="200" height="200" viewBox="0 0 300 300">
  <path fill="#7CBC96">
    <animate
      attributeName="d"
      dur="6s" 
      repeatCount="indefinite"
      values="M32.93,45.82 C58.31,...中略...23.3,53.73,32.93,45.82Z;
              M60,72.63 c25.38-20.82,...中略...,50.36,80.53,60,72.63Z;
              M60,72.63 c25.38-20.82,...中略...50.36,80.53,60,72.63Z;
              M54.58,55.36 c25.37-20.81,...中略...,63.26,54.58,55.36Z;
              M60.76,39.38 c25.38-20.81,...中略...,47.28,60.76,39.38Z;
              M32.93,45.82 C58.31,25,...中略...,53.73,32.93,45.82Z" />
    <animate
      attributeName="fill"
      dur="6s" 
      repeatCount="1"
      begin="click" 
      values="blue;
              yellow;
              green;
              red;
              purple;
              pink" />
  </path>  
</svg>

キーフレームの制御

keyTimes 属性を使わずに、values 属性のみを指定している場合、値の変化は自動的に時間全体に均等に分散されます。今までの例では keyTimes 属性を設定していないので、指定した値は時間全体に均等に分散されていました。

また、アニメーションの補間モードを指定する calcMode 属性のデフォルトは linear で、アニメーションは一定割合で徐々に変化します。今までの例では calcMode 属性を設定していないため linear が適用されてアニメーションは一定割合で徐々に変化するようになっていました。

keyTimes 属性

keyTimes 属性を使うと、区間ごとの時間(の比率)を指定することができます。

keyTimes 属性には値の変化が起こるタイミング(0〜1の間の比率を表す数値)のリストをセミコロン区切りで指定します。アニメーション開始が 0、終了が 1 です。

values 属性を使って値をしているキーフレームアニメーション場合、keyTimes 属性の値の個数は values 属性の値の個数に一致していなければなりません。

from/to/by を使ったアニメーションで keyTimes 属性を指定する場合、その値の個数は2でなければなりません。

また、keyTimes 属性に指定するリストの内容は calcMode 属性に指定した値に依存します。

  • calcMode が linear または spline の場合:最初の値が0、最後の値が1でなければならない
  • calcMode が discrete の場合:最初の値は 0 でなければならない
  • calcMode が paced の場合:keyTimes 属性は無視される

以下は前述の形状が変化するアニメーションに keyTimes 属性を指定して値の変化が起きるタイミングを調整した例です。前述の例では keyTimes 属性を指定していないので keyTimes="0; 0.333; 0.666; 1" を指定(区間を均等に分割)していたのとほぼ同じことになります。

<svg width="100" height="100" viewBox="0 0 100 100">
  <path fill="#1F66E1" opacity="0.7">
    <animate
attributeName="d"
dur="8s" 
repeatCount="indefinite"
values="M 0,0 L50,0 L100,0 L50,100;
     M 0,100 L50,0 L100,100 L50,100;
     M 0,100 L50,0 L100,100 L50,0;
     M 0,0 L50,0 L100,0 L50,100" 
keyTimes="0; 0.1; 0.9; 1" />
  </path>
</svg>
calcMode 属性

values 属性を使ったキーフレームアニメーションは、デフォルトでは各キーフレーム間を一定の変化量で補完する線形補間となりますが、calcMode 属性を指定することで変更することができます。

calcMode はアニメーションの補間モード(値の変化の関数)を指定する属性で、以下のような値を指定することができます。discrete を指定すると区間ごとに値は一気に変化し、linear では直線的に変化します。spline では指定されたベジェ曲線のカーブを描いて値が変化します。

calcMode 属性に指定できる値
説明
discrete 補完処理を行なわず、一つの値から次の値へ一気に移ります。
linear 各キーフレーム間を一定の変化量で補完。 animateMotion 要素以外での初期値。
paced 区間の距離によらずアニメーション全体にわたって一定の速度で移動(アニメーションの時間が、それぞれの区間の距離に比例して割り当てられます)
spline 三次ベジェ曲線(スプライン)による補完。keySplines 属性でベジェ曲線の制御点を指定します。値は数値4つ(x1 y1 x2 y2)を組として、それをセミコロン区切りで「キーフレームの数-1」個指定する必要があります(x1 y1 x2 y2 の値は0から1の間で指定)。

以下は calcMode 属性の値を変えた場合のアニメーションを確認する例です。

discrete linear paced spline
<svg width="400" height="120" viewBox="0 0 400 120">
  <rect width="400" height="80" x="0" y="0" fill="blue" opacity="0.1"/>
  <circle r="20" cx="20" cy="40" fill="red">
    <animate 
      attributeName="cx"
      values="20; 380; 100; 280; 200" 
      dur="3s"
      begin="rect_discrete.click"
      calcMode="discrete"
      fill="freeze"/>
    <animate 
      attributeName="cx"
      values="20; 380; 100; 280; 200" 
      dur="3s"
      begin="rect_linear.click"
      calcMode="linear"
      fill="freeze"/>
    <animate 
      attributeName="cx"
      values="20; 380; 100; 280; 200" 
      dur="3s"
      begin="rect_paced.click"
      calcMode="paced"
      fill="freeze"/>
    <animate 
      attributeName="cx"
      values="20; 380; 100; 280; 200" 
      dur="3s"
      begin="rect_spline.click"
      calcMode="spline" 
      keySplines="0.25 0.1 0.25 1.0; 0.42 0 1.0 1.0; 0.0 0.0 0.58 1.0; 0.42 0.0 0.58 1.0"
      fill="freeze"/>
  </circle>
  <rect id="rect_discrete" width="100" height="40" x="0" y="80" fill="blue" cursor="pointer"/>
  <rect id="rect_linear" width="100" height="40" x="100" y="80" fill="green" cursor="pointer"/>
  <rect id="rect_paced" width="100" height="40" x="200" y="80" fill="purple" cursor="pointer"/>
  <rect id="rect_spline" width="100" height="40" x="300" y="80" fill="darkorange" cursor="pointer"/>
  <text x="20" y="110" font-size="14" fill="white" pointer-events="none">discrete</text>
  <text x="130" y="110" font-size="14" fill="white" pointer-events="none">linear</text>
  <text x="230" y="110" font-size="14" fill="white" pointer-events="none">paced</text>
  <text x="330" y="110" font-size="14" fill="white" pointer-events="none">spline</text>
</svg>

上記の例では linear と paced の違いがあまりよくわかりませんが、paced は区間の距離によらずアニメーション全体にわたって一定の速度で移動する指定です。

以下の2つの円にはどちらも同じ移動距離が均等でない(20〜100、100〜280、280〜20)キーフレームアニメーションが設定されています。

calcMode 属性にデフォルトの linear を設定した赤い円は、区間ごとに時間が均等に割り振られるので区間によって移動速度が異なります。

calcMode 属性に paced を指定した青い円は、区間距離に応じて時間が割り当てられるので全区間にわたって一定の速度で移動します。

100 280
<svg width="300px" height="120px" viewBox="0 0 300 120">
  <circle cx="20" cy="20" r="20" fill="red">
    <animate
      attributeName="cx"
      dur="3s" 
      repeatCount="indefinite"
      values="20; 100; 280; 20"
      calcMode="linear" />
  </circle>
  <circle cx="20" cy="80" r="20" fill="blue">
    <animate
      attributeName="cx"
      dur="3s" 
      repeatCount="indefinite"
      values="20; 100; 280; 20"
      calcMode="paced" />
  </circle>
</svg>

以下は前述の path 要素のアニメーションの例に calcMode="discrete" を指定した例です。

d 属性の値を見ただけではそれぞれの形状はわかりにくいですが、飛び飛びに遷移するので values 属性に指定したそれぞれの時点においての path の d 属性の形状が確認できます(そのような必要はないかも知れませんが)。

<svg width="200" height="200" viewBox="0 0 300 300">
  <path fill="#7CBC96">
    <animate
      attributeName="d"
      dur="6s" 
      calcMode="discrete"
      repeatCount="indefinite"
      values="M32.93,45.82 C58.31,...中略...23.3,53.73,32.93,45.82Z;
              M60,72.63 c25.38-20.82,...中略...,50.36,80.53,60,72.63Z;
              M60,72.63 c25.38-20.82,...中略...50.36,80.53,60,72.63Z;
              M54.58,55.36 c25.37-20.81,...中略...,63.26,54.58,55.36Z;
              M60.76,39.38 c25.38-20.81,...中略...,47.28,60.76,39.38Z;
              M32.93,45.82 C58.31,25,...中略...,53.73,32.93,45.82Z" />
  </path>
</svg>    

以下は dur 属性に 1s を指定した例です。

クリックするとアニメーションが開始します(パラパラ動画のようになります)。

<svg width="200" height="200" viewBox="0 0 300 300">
  <path fill="#7CBC96" d="M32.93,45.82 C58.31,...中略...23.3,53.73,32.93,45.82Z">
    <animate
      attributeName="d"
      dur="1s" 
      calcMode="discrete"
      begin="click"
      repeatCount="3"
      values="M32.93,45.82 C58.31,...中略...23.3,53.73,32.93,45.82Z;
              M60,72.63 c25.38-20.82,...中略...,50.36,80.53,60,72.63Z;
              M60,72.63 c25.38-20.82,...中略...50.36,80.53,60,72.63Z;
              M54.58,55.36 c25.37-20.81,...中略...,63.26,54.58,55.36Z;
              M60.76,39.38 c25.38-20.81,...中略...,47.28,60.76,39.38Z;
              M32.93,45.82 C58.31,25,...中略...,53.73,32.93,45.82Z" />
  </path>
</svg>
keySplines 属性

keySplines 属性は keyTimes 属性で指定されたそれぞれの時間的な区間に対する値の変化のしかたを制御する3次ベジェ関数のリストを定義します。

calcMode 属性が spline に設定されていない場合、この属性は無視されます。

keySplines 属性は CSS アニメーションのアニメーションの速度変化を指定する animation-timing-function(タイミング関数:イージング)に該当します。

値はセミコロン区切りの4つの数値の組(x1 y1 x2 y2)を、keyTimes におけるそれぞれの時間の区間ごとに指定します。4つの数値(x1 y1 x2 y2)はスペースまたはカンマ区切りで指定します。

keySplines 属性に指定する値の個数は、キーフレームの数(keyTimes または values 属性に指定する値の個数)より1つ少なくなります(キーフレームの数 - 1)。

4つの数値の組(x1 y1 x2 y2)は、1つ目の制御点の座標(x1 y1)と2つ目の制御点の座標(x2 y2)から成り、値は0から1の間で指定し、それぞれの時間の区間に対応するベジェ制御点を定義するものです。

(0, 0) (1, 1) (x1, y1) (x2, y2) 時間

以下は cx と cy を対象としたアニメーションの values 属性に5つの値を指定して、keyTimes 属性で区切られたそれぞれの区間(4つの区間)での keySplines 属性を指定する例です。この例は Safari では機能しないようです。

最初の2つの区間では CSS の ease-in(ゆっくり入り加速して終わる)に該当する値を指定し、残りの2つの区間では

この例の場合、keyTimes 属性では均等に分割しているので keyTimes 属性を省略しても同じです。

<svg width="130" height="130" viewBox="0 0 130 130">
  <circle cx="60" cy="10" r="15" fill="lightskyblue">
    <animate attributeName="cx" dur="4s" repeatCount="indefinite" 
        calcMode="spline"
        values="60 ; 115 ; 60 ; 15 ; 60" 
        keyTimes="0 ; 0.25 ; 0.5 ; 0.75 ; 1"
        keySplines="0.42 0 1 1; 
                    0.42 0 1 1 ; 
                    0.5 0 0.5 1 ; 
                    0.5 0 0.5 1"/>
    <animate attributeName="cy" dur="4s" repeatCount="indefinite"
        calcMode="spline"
        values="15 ; 60 ; 115 ; 60 ; 15" 
        keyTimes="0 ; 0.25 ; 0.5 ; 0.75 ; 1"
        keySplines="0.42 0 1 1; 
                    0.42 0 1 1 ; 
                    0.5 0 0.5 1 ; 
                    0.5 0 0.5 1"/>
  </circle>
</svg>

以下は CSS アニメーションで指定するキーワードに対応する keySplines 属性の値です。

CSS イージングキーワードに対応する keySplines 属性の値
CSS でのイージングキーワード(説明) keySplines 属性の値
ease(急速に加速してゆっくり終わる) 0.25 0.1 0.25 1
linear(一定の速度) 0 0 1 1
ease-in(ゆっくり入り加速して終わる) 0.42 0 1 1
ease-out(速く入りゆっくり終わる) 0 0 0.58 1
ease-in-out(ease よりもゆっくり入り加速してゆっくり終わる) 0.42 0 0.58 1

以下のサイトにイージングのサンプルが掲載されています(cubic-bezier 関数の値を利用できます)

以下のサイトでは制御点の座標を操作して cubic-bezier 関数を編集して値をコピーすることができます。

開始 終了 ease linear ease-in ease-out ease-in-out
<svg width="300px" height="340px" viewBox="0 0 300 340">
  <circle cx="20" cy="20" r="15" fill="red">
    <animate
      attributeName="cx"
      dur="2s" 
      repeatCount="indefinite"
      begin="rect_keysplines_begin.click"
      end="rect_keysplines_end.click"
      values="20;280"
      calcMode="spline"
      keyTimes="0;1" 
      keySplines="0.25 0.1 0.25 1.0"/>
  </circle>
  <circle cx="20" cy="80" r="15" fill="green">
    <animate
      attributeName="cx"
      dur="2s" 
      repeatCount="indefinite"
      begin="rect_keysplines_begin.click"
      end="rect_keysplines_end.click"
      values="20;280"
      calcMode="spline"
      keyTimes="0;1" 
      keySplines="0.0 0.0 1.0 1.0"/>
  </circle>
  <circle cx="20" cy="140" r="15" fill="blue">
    <animate
      attributeName="cx"
      dur="2s" 
      repeatCount="indefinite"
      begin="rect_keysplines_begin.click"
      end="rect_keysplines_end.click"
      values="20;280"
      calcMode="spline"
      keyTimes="0;1" 
      keySplines="0.42 0 1.0 1.0"/>
  </circle>
  <circle cx="20" cy="200" r="15" fill="orange">
    <animate
      attributeName="cx"
      dur="2s" 
      repeatCount="indefinite"
      begin="rect_keysplines_begin.click"
      end="rect_keysplines_end.click"
      values="20;280"
      calcMode="spline"
      keyTimes="0;1" 
      keySplines="0.0 0.0 0.58 1.0"/>
  </circle>
  <circle cx="20" cy="260" r="15" fill="mediumpurple">
    <animate
      attributeName="cx"
      dur="2s" 
      repeatCount="indefinite"
      begin="rect_keysplines_begin.click"
      end="rect_keysplines_end.click"
      values="20;280"
      calcMode="spline"
      keyTimes="0;1" 
      keySplines="0.42 0.0 0.58 1.0"/>
  </circle>
  <rect id="rect_keysplines_begin" x="50" y="300" width="80" height="30" rx="5" ry="5" fill="gold" cursor="pointer"/>
  <rect id="rect_keysplines_end" x="150" y="300" width="80" height="30" rx="5" ry="5" fill="silver" cursor="pointer"/>
  <text x="70" y="320" font-size="14" fill="black" pointer-events="none">開始</text>
  <text x="170" y="320" font-size="14" fill="black" pointer-events="none">終了</text>
  <text x="40" y="25" font-size="16" fill="silver">ease</text>
  <text x="40" y="85" font-size="16" fill="silver">linear</text>
  <text x="40" y="145" font-size="16" fill="silver">ease-in</text>
  <text x="40" y="205" font-size="16" fill="silver">ease-out</text>
  <text x="40" y="265" font-size="16" fill="silver">ease-in-out</text>
</svg>

設定値を制御する属性

前のアニメーションが終了した位置から開始するアニメーションや前のアニメーションの値の状態(累積合計)を使用して続行するアニメーションを定義する場合には、additive 属性や accumulate 属性を使用することができます。

additive 属性

additive 属性を使うと、アニメーションで計算された値を属性値に反映させる処理を指定することができ、以下のいずれかを指定できます。

  • replace(上書き:デフォルト)
  • sum (元の値に加算)

additive 属性を sum に設定すると、各値はアニメーション対象属性の元の値を基準にします。

また、この属性の値を sum に設定することで、単一の属性に複数のアニメーションを定義して、その値を足し合わせることができます。

以下はアニメーション対象属性を cx とした移動アニメーションの例です。

1つ目の円には additive="sum" を指定しているため、from="0" と to="230" は、実際には元の値 50 に加算されて from="50" と to="280" となります。

2つ目の円は初期値の replace を指定しているので、アニメーションは from="0" と to="230" の間を移動します。

<svg width="300" height="150" viewBox="0 0 300 150">
  <circle r="20" cx="50" cy="30" fill="lightblue">
    <animate 
    attributeName="cx"
    from="0"
    to="230" 
    additive="sum"
    repeatCount="3"
    dur="2s"
    begin="click"
    fill="freeze" />
  </circle>
  <circle r="20" cx="50" cy="90" fill="lightgreen">
    <animate 
    attributeName="cx"
    from="0"
    to="230" 
    additive="replace"
    repeatCount="3"
    dur="2s"
    begin="click"
    fill="freeze" />
  </circle> 
</svg>
50 230 280
同一属性に複数のアニメーションを定義

同じ属性に複数のアニメーションを設定すると、それぞれのアニメーションが要素の属性値を上書きしていくため、通常は最後のアニメーション要素のみが有効になり、他は無視されます。

この挙動は additive 属性に sum を指定することで変更することができます。

animateTransform 要素による変形アニメーションの場合、移動・回転・スケール・スキューが同じ transform 属性に集約されているため、複数の変形アニメーションを同時に適用するには additive="sum" を指定する必要があります。

以下は、additive="sum" を指定して1つの属性に2つのアニメーションを適用する例です。

2つ目の円は additive="sum" を指定していないので、2つ目(最後)のアニメーション要素のみが有効になります。

<svg width="300" height="120" viewBox="0 0 300 120">
  <circle r="20" cx="20" cy="30" fill="pink">
    <animate
      attributeName="cx"
      dur="10s" 
      values="20; 180; 20"
      repeatCount="indefinite"
      repeatDur="10s"
      begin="click"
      fill="freeze"/>
    <animate
      attributeName="cx"
      dur="1.3s" 
      values="0; 100; 0"
      repeatCount="indefinite" 
      repeatDur="10s"
      begin="click"
      fill="freeze"
      additive="sum" />
  </circle>
  <circle r="20" cx="20" cy="90" fill="gold">
    <animate
      attributeName="cx"
      dur="10s" 
      values="20; 180; 20"
      repeatCount="indefinite"
      repeatDur="10s"
      begin="click"
      fill="freeze"/>
    <animate
      attributeName="cx"
      dur="1.3s" 
      values="0; 100; 0"
      repeatCount="indefinite"
      repeatDur="10s"
      begin="click"
      fill="freeze"/>
  </circle> 
</svg> 
accumulate 属性

2回目の繰り返しが前の繰り返しの終了値から始まるように値を追加したいような場合は accumulate 属性を使います。

accumulate 属性はアニメーションが累積されるかどうかを制御します。 デフォルト値は none で、例えばアニメーションが繰り返されると最初からやり直しになります。

sum に設定することで、最初の反復の後の各反復が前の反復の最後の値に基づいて実行されます。

但し、対象の属性値が加算をサポートしていない場合や、アニメーション要素が繰り返されない場合は accumulate 属性は無視されます。

また、アニメーション関数が to 属性のみで指定されている場合も無視されます。

以下は、accumulate 属性にsum にを指定して、移動の繰り返しを前の繰り返しの終了値から始まるようにする例です。わかりやすいように、calcMode 属性に spline を指定し keySplines 属性を指定しています。

<svg width="300" height="40">
  <circle r="20" cx="20" cy="20" fill="mediumpurple">
    <animate 
      attributeName="cx"
      from="0"
      to="80" 
      additive="sum"
      accumulate="sum"
      repeatCount="3"
      calcMode="spline"
      keyTimes="0;1"
      keySplines="0.25 0.1 0.25 1"
      dur="1s"
      begin="click"
      fill="freeze" />
  </circle>        
</svg>

set 要素

set 要素は指定された持続時間だけ属性に値を設定するための手段を提供します。文字列や真偽値などの通常の補間ができないものも含めたすべての属性型をサポートします。

但し、set 要素は非加法的(非加算的)要素で additive 属性と accumulate 属性は許可されておらず、指定されている場合は無視されます。

また、set 要素は特定の期間に特定の値に要素を設定する目的で使用されるため、from 属性または by 属性はありません。

基本的な使い方(対象の要素の指定対象となる属性の特定)は animate 要素と同じで、to 属性で値を指定でき、アニメーションのタイミングは、begin、dur、end、min、max、restart、repeatCount、repeatDur、fill 属性で制御できます。

以下は、set 要素を使って塗り色(fill)と半径(r)を一定期間変更する例です。

ドキュメント読み込み後2秒したら id が set1 の set 要素により色がオレンジから水色に変更され、set1 が終了するとその他の set 要素により半径と色が変更されます。

id が set1 の set 要素の begin 属性には set2.end を指定してあるので、アニメーションは繰り返されます。

<svg width="100px" viewBox="0 0 100 100">
  <circle cx="50" cy="50" r="50" fill="orange">
    <set id="set1" attributeName="fill" begin="2s; set2.end" dur="2s" to="lightblue"/>
    <set attributeName="r" begin="set1.end" dur="2s" to="30"/>
    <set id="set2" attributeName="fill" begin="set1.end" dur="4s" to="pink"/>
  </circle>
</svg>

以下は、クリックすると set 要素を使って移動する円の色をピンクに設定する例です。色は3秒間ピンクのままでその後元の色に戻ります。円がクリックされるたびに設定されたアニメーションが起動され、色が3秒間変更されます。

<svg width="300" height="40">
  <circle r="20" cx="20" cy="20" fill="green">
    <animate 
      attributeName="cx"
      values="20; 280; 20"
      repeatCount="indefinite"
      dur="20s"
      begin="0s"/>
    <set 
      attributeName="fill"
      to="pink" 
      begin="click" 
      dur="3s" />
  </circle>        
</svg> 

以下は円を移動するアニメーションの特定の繰り返しごとに、set 要素を使って円の色(fill)と大きさ(r)を変化させる例です(繰り返し回数に基づいてアニメーションを同期)。この例も Safari では機能しないようです。

<svg width="300px" height="50px" viewBox="0 0 300 50">      
  <circle cx="20" cy="20" r="20" fill="pink">
    <animate id="repeat_animation2" 
             repeatCount="3"
             attributeName="cx"
             values="20; 280; 20"
             dur="4s" 
             begin="0s; repeat_animation2.end"
             calcMode="spline" 
             keyTimes="0 ;0.5 ; 1"
             keySplines="0.42 0 0.58 1; 
                         0.42 0 0.58 1"/>
    <set attributeName="fill"
         begin="repeat_animation2.begin" 
         to="pink" />
    <set attributeName="r"
         begin="repeat_animation2.repeat(1)" 
         to="10"
         dur="2s"/>
    <set attributeName="fill"
         begin="repeat_animation2.repeat(1)" 
         to="purple" />
    <set attributeName="fill"
         begin="repeat_animation2.repeat(2)" 
         to="lightblue" />
    <set attributeName="r"
         begin="repeat_animation2.repeat(2)" 
         to="5"
         dur="1s"/>
  </circle>   
</svg>

animateMotion 要素

animateMotion 要素を使うとパスに沿って要素を移動できます。使い方は path 属性または mpath 要素を使ってパスを指定する方法と values や from、to、by などを使って座標のリストを指定する方法があります。

animateMotion 要素では前述の animate 要素で使用できる属性に加えて、keyPoints、rotate、path の3つの属性及びモーションパスの定義として path 要素を参照する mpath 要素が用意されています。

animateMotion 要素で使用できる属性
属性 説明
path モーションパスを定義する属性で、値の指定構文とその解釈は path 要素の d 属性と同じ。
keyPoints 対応する keyTimes 属性で指定された値による時刻において、モーションパスに沿ってオブジェクト(対象の要素)をどれだけの距離まで動かすかを指定。パス全体の長さにおける位置を0から1の間の割合で設定。
rotate 図形の回転角を指定(数値 | auto | auto-reverse)既定値は 0

また、animateMotion 要素の calcMode 属性のデフォルト値は linear ではなく paced になっています。

path 属性を使ってモーションパスを定義

path 属性はモーションパスを指定するために使用され、path 要素の d 属性と同じ形式で定義され、同じ方法で解釈されます。

モーションパスアニメーションの効果は、参照されるオブジェクトの現在の変換行列に補足の変換行列を追加することで、時間経過とともに計算されたX値とY値によって現在のユーザー座標系のx軸とy軸に沿って移動が発生します。

指定されたパスはパスデータを使用して要素をパス位置に変換することにより、要素の現在の位置を基準にして計算されます。

パスデータの座標

path 属性に指定する最初の M コマンドの座標はモーションパスの開始位置になりますが、path 属性の座標は要素の現在の位置を基準にしています(現在の位置に対して相対的です)。

そのため、最初の M コマンドに続く座標(0, 0)は座標系の左上隅ではなく、実際には移動する要素の最初の位置になります。

以下は path 要素で描画した曲線上に沿って円を移動させるモーションパスアニメーションの例です。

path 要素で描画した曲線に指定している d 属性の値と全く同じ値を animateMotion 要素の path 属性に指定しています。

この例ではアニメーションの軌道を確認するために path 要素を使ってパスを描画しています(path 要素を使う必要はありません)。

<svg width="300px" height="250px" viewBox="0 0 300 250">
  <circle r="10" cx="10" cy="40" fill="tomato">
    <animateMotion 
       dur="4s"
       begin="click"
       repeatCount="1"
       fill="freeze"
       path="M10 40 C50 100,90 140,160 60 S230 0,280 40"/>
  </circle>
  <path d="M10 40 C50 100,90 140,160 60 S230 0,280 40" stroke="#999" stroke-width="1" fill="transparent"/>
</svg>

円をクリックするとアニメーションが開始されます。但し、この場合、曲線の上を移動せず、曲線に沿った移動になります。

※ M コマンドに指定する最初の座標(始点)を (0, 0) 以外の点から指定すると、始点で指定した量だけ要素(この場合は円)が急にジャンプすることになります。

path 属性の座標は要素の現在の位置を基準にしているので(現在の位置に対して相対的なため)、実際のアニメーションの開始位置は M コマンドの座標(10, 40)と circle 要素の位置(10, 40)から (20, 80) になり、終了位置は(290, 80)になります。

円をクリックして一度アニメーションを実行後、再度円をクリックすると (20, 80)からアニメーションが再開するのが確認しやすいです。

(0, 0) (10, 40) (280, 40) (20, 80) (290, 80)
<svg width="300px" height="160px" viewBox="0 0 300 160" style="overflow:visible">
  <line x1="0" y1="0" x2="300" y2="0" stroke="#ccc" stroke-width="1" stroke-dasharray="3"/>
  <line x1="0" y1="0" x2="0" y2="150" stroke="#ccc" stroke-width="1" stroke-dasharray="3"/>
  <circle r="3" cx="0" cy="0" fill="#999"/>
  <text x="-10" y="-10" font-size="12" fill="#999">(0, 0)</text>
  <text x="30" y="45" font-size="12" fill="blue">(10, 40)</text>
  <text x="210" y="45" font-size="12" fill="blue">(280, 40)</text>
  <text x="0" y="110" font-size="12" fill="green">(20, 80)</text>
  <text x="220" y="85" font-size="12" fill="green">(290, 80)</text>
  <circle r="10" cx="10" cy="40" fill="tomato">
    <animateMotion 
       dur="4s"
       begin="click"
       repeatCount="1"
       fill="freeze"
       path="M10 40 C50 100,90 140,160 60 S230 0,280 40"/>
  </circle>
  <path d="M10 40 C50 100,90 140,160 60 S230 0,280 40" stroke="#999" stroke-width="1" fill="transparent" pointer-events="none"/>
  <circle r="3" cx="10" cy="40" fill="blue" pointer-events="none"/>
  <circle r="3" cx="280" cy="40" fill="blue" pointer-events="none"/>
  <circle r="3" cx="290" cy="80" fill="green" pointer-events="none"/>
  <circle r="3" cx="20" cy="80" fill="green" pointer-events="none"/>
</svg> 

以下は円の中心座標を cx="0" cy="0" とした例です。この場合、円はパスの上を移動します。

(0, 0)
<svg width="300px" height="160px" viewBox="0 0 300 160" style="overflow:visible">
  <circle r="10" cx="0" cy="0" fill="tomato">
    <animateMotion 
       dur="4s"
       begin="click"
       repeatCount="1"
       fill="freeze"
       path="M10 40 C50 100,90 140,160 60 S230 0,280 40"/>
  </circle>
  <path d="M10 40 C50 100,90 140,160 60 S230 0,280 40" stroke="#999" stroke-width="1" fill="transparent" pointer-events="none"/>
</svg>

以下は、path 要素の d 属性及び path 属性の M コマンドの座標(始点)のみを(0, 0)に変更した例です。この場合、パスの形状が変わっています。

(0, 0)
<svg width="300px" height="160px" viewBox="0 0 300 160" style="overflow:visible">
  <circle r="10" cx="0" cy="0" fill="tomato">
    <animateMotion 
       dur="4s"
       begin="click"
       repeatCount="1"
       fill="freeze"
       path="M0 0 C50 100,90 140,160 60 S230 0,280 40"/>
  </circle>
  <path d="M0 0 C50 100,90 140,160 60 S230 0,280 40" stroke="#999" stroke-width="1" fill="transparent" pointer-events="none"/>
</svg>

以下は、path 要素の d 属性は元のままで、path 属性の値をすべて編集して、M コマンドの座標を(0, 0)に変更した例です。この場合、パスの形状が変わらないように値を編集しています。

(0, 0) (10, 40)
<svg width="300px" height="160px" viewBox="0 0 300 160" style="overflow:visible;">
  <line x1="0" y1="0" x2="300" y2="0" stroke="#ccc" stroke-width="1" stroke-dasharray="3"/>
  <line x1="0" y1="0" x2="0" y2="150" stroke="#ccc" stroke-width="1" stroke-dasharray="3"/>
  <circle r="3" cx="0" cy="0" fill="#999"/>
  <text x="-10" y="-10" font-size="12" fill="#999">(0, 0)</text>
  <circle r="10" cx="10" cy="40" fill="tomato">
    <animateMotion 
       dur="4s"
       begin="click"
       repeatCount="1"
       fill="freeze"
       path="M0 0 C40 60,80 100,150 20 S220 -40,270 0"/>
       <!-- path 属性の値を M0 0 から始まるように書き換え-->
  </circle>
  <path d="M10 40 C50 100,90 140,160 60 S230 0,280 40" stroke="#999" stroke-width="1" fill="transparent" pointer-events="none"/>
</svg>

mpath 要素を使ってモーションパスを指定

path 属性を使用する代わりに、mpath 要素を使用して外部パスを参照してモーションパスを指定することができます。

mpath 要素は animateMotion 要素の子要素として配置し、xlink:href 属性を使用して別途 path 要素で定義した外部パスを参照します。

以下は id が motion_path1 の path 要素でパスを描画し、animateMotion 要素の子要素として配置した mpath 要素で xlink:href 属性を使って参照してモーションパスアニメーションを行う例です。

<svg width="300px" height="160px" viewBox="0 0 300 160">
  <path id="motion_path1" d="M10 40 C50 100,90 140,160 60 S230 0,280 40" stroke="#999" stroke-width="1" fill="transparent"/>
  <circle r="10" cx="10" cy="40" fill="tomato">
    <animateMotion dur="4s" begin="click" repeatCount="1" fill="freeze">
      <mpath xlink:href="#motion_path1" />
    </animateMotion>
  </circle>
</svg>

円をクリックするとアニメーションが開始されます。但し、path 属性を使用した場合と同様、円の中心座標が(0,0)でないため曲線の上を移動せず、曲線に沿った移動になります。

以下は円の中心座標を0(cx="0" cy="0")にした例で、この場合はパスの上を移動します。円の一部が viewBox の外にはみ出してしまうので、style="overflow:visible;" を指定しています。

<svg width="300px" height="160px" viewBox="0 0 300 160" style="overflow:visible;">
  <path id="motion_path2" d="M10 40 C50 100,90 140,160 60 S230 0,280 40" stroke="#999" stroke-width="1" fill="transparent"/>
  <circle r="10" cx="0" cy="0" fill="tomato">
    <animateMotion dur="4s" begin="click" repeatCount="1" fill="freeze">
      <mpath xlink:href="#motion_path2" />
    </animateMotion>
  </circle>
</svg>

以下は前述と同じモーションパスアニメーションを repeatCount 属性に "indefinite" を指定して繰り返す例です。この例では円の中心座標を transform 属性の translate() 関数で(0,0)に移動しています。

<svg width="300px" height="250px" viewBox="0 -10 300 250">
  <path id="mpath1" d="M10 40 C50 100,90 140,160 60 S230 0,280 40" stroke="#999" stroke-width="1" fill="transparent"/>
  <circle id="circle1" r="10" cx="10" cy="40" fill="tomato" transform="translate(-10, -40)" />
  <animateMotion 
    xlink:href="#circle1"
    dur="4s"
    begin="0s"
    repeatCount="indefinite"
    fill="freeze">
    <mpath xlink:href="#mpath1" />
  </animateMotion>
</svg>

以下は円が閉じたパス上を繰り返し移動するモーションパスアニメーションの例です。

<svg width="160px" height="200px" viewBox="0 0 160 200" style="overflow:visible;">
  <path id="motion_path3" d="M103.254,46.379c-0.43-15.914-9.589-28.923-21.8-20.986C77.13,28.2,74.782,33.625,70.5,36.514c-3.938,2.658-8.851,3-13.45,2.984-9.312-.035-20.139-4.126-22.935,8.669-1.9,8.712,9.095,14.268,6.408,22.656-0.838,2.62-3.445,4.558-5.585,6.193-5.317,4.061-9.276,7.551-13.212,13.322-7.371,10.8-7.894,15.829-5.317,22.629,2.795,7.372,13.244,14.292,21.915,10.834,10.4-4.146,9.418-13,20.992-17.578,9.768-3.869,12.741,4.426,16.4,11.212,6.909,12.8,20.33,12.313,29.47,1.2,2.977-3.619,8.057-11.529,7.052-16.709-0.812-4.181-6.284-6.7-8.935-9.535-9.325-9.959,6.339-13.538,14.554-17.2,7.851-3.5,20.509-10.686,16.328-23.656-1.435-4.451-11.438-8.433-15.47-6.882C113.019,46.854,103.419,52.534,103.254,46.379Z" stroke="#999" stroke-width="1" fill="transparent" stroke-dasharray="2"/>
  <circle r="10" cx="0" cy="0" fill="lightseagreen">
    <animateMotion dur="5s" begin="click; rect_start.click" end="rect_stop.click" fill="freeze" repeatCount="indefinite" >
      <mpath xlink:href="#motion_path3" />
    </animateMotion>
  </circle>
  <!-- 以下は「開始」と「終了」ボタンの長方形とテキスト -->
  <rect id="rect_start" x="0" y="150" width="60" height="30" fill="darkblue" cursor="pointer"/>
  <rect id="rect_stop" x="80" y="150" width="60" height="30" fill="darkred" cursor="pointer"/>
  <text x="15" y="170" font-size="14" fill="white" pointer-events="none">開始</text>
  <text x="95" y="170" font-size="14" fill="white" pointer-events="none">終了</text>
</svg>

開始ボタンか円をクリックするとアニメーションを開始します。終了ボタンをクリックすると終了します。

開始 終了

values を指定したモーションパス

path 属性や mpath 要素でモーションパスを指定する代わりに、from、to、by、values を使って座標のリストを指定することもできます。

values 属性を指定する場合、その値は X, Y 座標成分の対からなるセミコロン区切りのリストで指定する必要があります。

座標成分は少なくとも1個の空白文字またはコンマで区切られていなければならず、区切り文字の前後に空白文字があってもかまいません。

以下は animateMotion 要素の values 属性に座標のリストを指定する例です。

移動させる円の中心座標は cx="0" cy="0" を指定しています。

path 要素でパス図形を描画していますが(以下の例では塗りも指定)、この場合、animateMotion 要素に必要なわけではないので不要であれば省略できます。

<svg width="150px" height="150px" viewBox="0 0 150 150">
  <path d="M10 10 L10 60 L50 60 L50 100 L10 100 L10 140 L140 140 L90 60 L140 10 Z" stroke="#ccc" fill="blue" fill-opacity="0.1"/>
  <circle r="10" cx="0" cy="0" fill="red" fill-opacity="0.7">
    <animateMotion 
      values="10,10; 10,60; 50,60; 50,100; 10,100; 10,140; 140,140; 90,60; 140,10; 10,10" 
      begin="0s" 
      dur="10s" 
      repeatCount="indefinite"/>
  </circle>
</svg>

以下は上記と同じことを mpath 要素を使って行う例です。

この場合、前述の例とは異なり、path 要素は mpath 要素に参照されているので(モーションパスを定義しているので)省略することはできません。

<svg width="150px" height="150px" viewBox="0 0 150 150">
  <path id="motion_path4" d="M10 10 L10 60 L50 60 L50 100 L10 100 L10 140 L140 140 L90 60 L140 10 Z" stroke="#ccc" fill="blue" fill-opacity="0.1"/>
  <circle r="10" cx="0" cy="0" fill="blue" fill-opacity="0.5">
    <animateMotion dur="10s" begin="0s" repeatCount="indefinite" >
      <mpath xlink:href="#motion_path4"/>
    </animateMotion>
  </circle>
</svg>

keyPoints 属性で距離を制御

keyPoints 属性を使うと keyTimes 属性で指定する各時点でオブジェクトをモーションパスに沿ってどれだけ移動するかを指示することができます。

keyPoints 属性の値には、パス全体の長さにおける位置を0から1の間の割合を表す小数点値をセミコロン区切りで指定します。

keyPoints を指定する場合、keyPoints リストには keyTimes リストと同じ数の値が必要です。

また、keyPoints がうまく機能するようにするためには、calcMode 属性の値を linear(paced 以外)に設定します(animateMotion 要素の calcMode のデフォルトは paced で一定の速度になってしまうため)。

以下は keyPoints="0; 0.7; 1" と keyTimes="0; 0.2; 1" を指定し、パス全体の70%の距離を20%の時間で移動し、残りの30%の距離を80%の時間で移動させる例です。

<svg width="300px" height="160px" viewBox="0 0 300 160" style="overflow:visible;">
  <path d="M10 40 C50 100,90 140,160 60 S230 0,280 40" stroke="#999" stroke-width="1" fill="transparent"/>
  <circle r="10" cx="10" cy="40" fill="tomato">
    <animateMotion 
       dur="3s"
       begin="click"
       repeatCount="1"
       fill="freeze"
       path="M0 0 C40 60,80 100,150 20 S220 -40,270 0"
       calcMode="linear" 
       keyPoints="0; 0.7; 1" 
       keyTimes="0; 0.2; 1"/>
  </circle>
</svg>

以下は calcMode 属性に "spline" を指定した例です。

<svg width="300px" height="160px" viewBox="0 0 300 160" style="overflow:visible;">
  <path d="M10 40 C50 100,90 140,160 60 S230 0,280 40" stroke="#999" stroke-width="1" fill="transparent"/>
  <circle r="10" cx="10" cy="40" fill="tomato">
    <animateMotion 
       dur="3s"
       begin="click"
       repeatCount="1"
       fill="freeze"
       path="M0 0 C40 60,80 100,150 20 S220 -40,270 0"
       calcMode="spline" 
       keySplines="0.25 0.1 0.25 1; 0.42 0 1 1"
       keyPoints="0; 0.5; 1" 
       keyTimes="0; 0.5; 1"/>
  </circle>
</svg>

以下は keyPoints でパス全体を4等分して、それぞれ異なる keyTimes の値を指定した例です。

<svg width="160px" height="160px" viewBox="0 0 160 160" style="overflow:visible;">
  <path id="motion_path5" d="M103.254,46.379c-0.43-15.914-9.589-28.923-21.8-20.986C77.13,28.2,74.782,33.625,70.5,36.514c-3.938,2.658-8.851,3-13.45,2.984-9.312-.035-20.139-4.126-22.935,8.669-1.9,8.712,9.095,14.268,6.408,22.656-0.838,2.62-3.445,4.558-5.585,6.193-5.317,4.061-9.276,7.551-13.212,13.322-7.371,10.8-7.894,15.829-5.317,22.629,2.795,7.372,13.244,14.292,21.915,10.834,10.4-4.146,9.418-13,20.992-17.578,9.768-3.869,12.741,4.426,16.4,11.212,6.909,12.8,20.33,12.313,29.47,1.2,2.977-3.619,8.057-11.529,7.052-16.709-0.812-4.181-6.284-6.7-8.935-9.535-9.325-9.959,6.339-13.538,14.554-17.2,7.851-3.5,20.509-10.686,16.328-23.656-1.435-4.451-11.438-8.433-15.47-6.882C113.019,46.854,103.419,52.534,103.254,46.379Z" stroke="#999" stroke-width="1" fill="transparent" stroke-dasharray="2"/>
  <circle r="10" cx="0" cy="0" fill="lightseagreen">
    <animateMotion 
       dur="5s" 
       begin="click; rect_start2.click" 
       end="rect_stop2.click" 
       fill="freeze" 
       repeatCount="indefinite" 
       calcMode="linear" 
       keyPoints="0; 0.25; 0.5; 0.75; 1" 
       keyTimes="0; 0.3; 0.4; 0.6; 1">
      <mpath xlink:href="#motion_path5" />
    </animateMotion>
  </circle>
  <rect id="rect_start2" x="0" y="150" width="60" height="30" fill="darkblue" cursor="pointer"/>
  <rect id="rect_stop2" x="80" y="150" width="60" height="30" fill="darkred" cursor="pointer"/>
  <text x="15" y="170" font-size="14" fill="white" pointer-events="none">開始</text>
  <text x="95" y="170" font-size="14" fill="white" pointer-events="none">終了</text>
</svg> 
開始 終了

以下は values を指定したモーションパスの例です(keyPoints 属性は使用していません)。

values を使う場合はキーフレームと同様、keyTimes 属性に同じ数の値を指定して区間のスピードを制御することができます。

<svg width="150px" height="150px" viewBox="0 0 150 150">
  <path d="M10 10 L10 60 L50 60 L50 100 L10 100 L10 140 L140 140 L90 60 L140 10 Z" stroke="#ccc" fill="blue" fill-opacity="0.1"/>
  <circle r="10" cx="0" cy="0" fill="orange" fill-opacity="0.7">
    <animateMotion 
      values="10,10; 10,60; 50,60; 50,100; 10,100; 10,140; 140,140; 90,60; 140,10; 10,10" 
      begin="0s" 
      dur="8s" 
      repeatCount="indefinite"
      calcMode="linear" 
      keyTimes="0; 0.03; 0.1; 0.12; 0.18; 0.2; 0.4; 0.45; 0.6; 1"/>
  </circle>
</svg>

rotate 属性でパスに沿って要素を回転

今までの例ではパスに沿ってアニメーションさせていた要素は円でしたが、特定の方向を持つ要素をアニメーション化する際に回転の処理が必要になる場合があります。

rotate 属性を使うと、対象の要素に回転変換(回転処理)を適用することができます。

rotate 属性は、次の3つの値のいずれかを取ります。

rotate 属性に指定できる値
説明
数値 対象の要素に適用する回転角を度数で指定します。初期値:0
auto 対象の要素をモーションパスの方向の角度(方向の接線ベクトル)だけ時間の経過とともに自動的に回転させます。
auto-reverse 対象の要素をモーションパスの方向の角度(方向の接線ベクトル)に180度を加えた角度で時間の経過とともに自動的に回転させます。

次の例では、以下のような車のアイコンを使用します。このアイコンは Photoshop のカスタムシェイプで作成しています(関連ページ:Photoshop で SVG

<svg width="40px" height="24px" viewBox="0 0 40 24" style="margin: 30px 0;">
<path fill="rgb(220, 7, 7)"
 d="M0.804,15.876 C0.894,15.779 1.279,15.495 1.304,15.399 C1.395,15.049 1.496,14.480 1.571,14.015 C2.169,10.123 13.246,3.494 16.337,2.006 C21.485,-0.477 25.955,-0.088 30.704,0.249 C31.631,0.315 32.726,0.377 33.555,0.837 C33.591,0.860 33.625,0.877 33.653,0.899 C34.986,1.593 36.672,3.246 37.578,7.185 C37.717,7.625 37.832,8.076 37.905,8.535 C38.074,9.583 37.988,10.652 38.304,11.677 C38.583,12.582 39.077,13.417 39.288,14.344 C39.378,14.733 40.034,16.683 39.555,17.066 C39.838,17.680 39.997,18.362 39.997,19.080 C39.997,21.796 37.745,23.999 34.969,23.999 C32.668,23.999 30.729,22.401 30.159,20.532 C30.159,20.532 16.076,20.548 10.728,20.548 C10.083,22.547 8.195,23.999 5.942,23.999 C3.649,23.999 1.726,22.502 1.115,20.457 C-0.518,19.758 -0.115,16.890 0.804,15.876 L0.804,15.876 ZM35.397,3.859 C34.514,2.269 33.367,1.213 32.829,1.498 C32.296,1.780 32.575,3.297 33.457,4.891 C34.338,6.479 35.485,7.538 36.023,7.251 C36.560,6.968 36.277,5.448 35.397,3.859 L35.397,3.859 ZM34.969,21.490 C36.328,21.490 37.434,20.408 37.434,19.080 C37.434,17.748 36.328,16.670 34.969,16.670 C33.607,16.670 32.504,17.748 32.504,19.080 C32.504,20.408 33.607,21.490 34.969,21.490 L34.969,21.490 ZM29.106,7.320 C30.159,7.237 31.061,6.322 30.926,5.290 C30.732,3.824 30.180,1.953 28.633,1.514 C27.063,1.067 24.709,1.153 23.060,1.292 C22.006,1.386 20.332,1.758 19.335,2.116 C16.868,3.006 12.505,4.837 10.174,7.374 C9.465,8.144 9.941,8.844 10.994,8.760 L29.106,7.320 ZM5.942,21.490 C7.299,21.490 8.406,20.408 8.406,19.080 C8.406,17.748 7.299,16.670 5.942,16.670 C4.584,16.670 3.477,17.748 3.477,19.080 C3.477,20.408 4.584,21.490 5.942,21.490 L5.942,21.490 Z"/>
</svg>

以下は車のアイコンを移動させるモーションパスです(こちらも Photoshop のカスタムシェイプを使って作成しています)。

<svg width="260" height="200" viewBox="0 0 260 200">
  <path fill="transparent" stroke="gray" d="M196.722,94.707c16.6-20.633,18.987-47.006-5.073-50.133-8.512-1.106-17.338,3.233-25.887,2.273-7.865-.882-14.472-5.752-20.294-10.738-11.787-10.1-21.127-26.97-38.462-13.772-11.8,8.986-3.825,27.9-16.274,35.631-3.887,2.416-9.285,2.058-13.765,1.82-11.127-.593-19.914-0.444-31.131,2.62C24.843,68.136,18.758,73.947,14.7,85.347c-4.395,12.36,1.418,32.41,16.154,37.389,17.676,5.975,25.961-6.305,45.595.383,16.572,5.641,11.41,19.364,8.749,31.919-5.02,23.683,12.549,37.552,36.126,33.339,7.681-1.374,22.653-5.913,26.958-13.564,3.474-6.175-.757-15.279-1.073-21.73C146.1,130.4,169.849,142.769,184.223,147c13.736,4.046,37.556,8.6,46.222-12.354,2.973-7.189-5.438-23.036-12.228-25.422C208.61,105.852,190.3,102.687,196.722,94.707Z"/>
</svg>

以下は上記の車のアイコンとパスを使ったモーションパスアニメーションの例です。

この例では mpath 要素を使用して id が car_mpath の path 要素を参照してモーションパスを指定しています。

animateMotion 要素の xlink:href で車のアイコンの id(car)を指定してモーションパスアニメーションを実行しています。

<svg width="300" height="250" viewBox="0 0 300 250">
  <!-- モーションパス -->
  <path 
    id="car_mpath" 
    fill="none" 
    stroke="gray" 
    d="M196.722,94.707c16.6-20.633, ...中略... 196.722,94.707Z"/>
  <!-- 車のアイコン -->
  <path 
    id="car" 
    fill="rgb(220, 7, 7)" 
    d="M0.804,15.876 C0.894,15.779 ...中略... L5.942,21.490 Z"/>
  <animateMotion 
    xlink:href="#car"
    dur="10s"
    begin="0s"
    fill="freeze"
    repeatCount="indefinite">
    <mpath xlink:href="#car_mpath" />
  </animateMotion>
</svg>

この例の場合、移動させる対象の要素(車のアイコン)の初期位置が(0,0)ではないため、モーションパスから少しずれて移動しています。

モーションパス上を移動するようにさせるには、transform 属性の translate() 関数を使って対象の要素(車のアイコン)の位置を調整します。

車のアイコンの path 要素の d 属性の最初の M コマンドの座標(初期位置)を(0,0)になるようにすればよいので、例えば以下のようにします。

d 属性の M コマンドは「M0.804,15.876」となっているので、(0,0)にするには translate(-0.804, -15.876) を指定しますが、この場合X軸方向を若干調整して translate(-15, -15.876) としています。

<path 
  id="car" 
  transform="translate(-15, -15.876)" 
  fill="rgb(220, 7, 7)" 
  d="M0.804,15.876 C0.894,15.779 ...中略... L5.942,21.490 Z"/>

auto

rotate 属性に auto を指定すると、対象の要素をモーションパスの方向の角度に自動的に回転させてくれます。以下は rotate="auto" を指定した例です。パスの内側を角度を自動調整して移動します。

<animateMotion 
  xlink:href="#car"
  dur="10s"
  begin="0s"
  fill="freeze"
  rotate="auto"
  repeatCount="indefinite">
  <mpath xlink:href="#car_mpath" />
</animateMotion>

但し、この例の場合、車の向きが逆側になってしまっています。逆向きのアイコンを使用ることもできますが、車のアイコンの要素を transform 属性の scale() 関数を使って反転することができます。

以下のように scale() の値に負の値を設定することで図形を反転することができます。

以下はX軸方向に反転する例です。scale (-1, -1) とするとY軸方向にも反転され、rotate 属性の値に auto-reverse を指定したのと同じになります。

<path 
  id="car" 
  transform="scale (-1, 1) translate(-15, -15.876)" 
  fill="rgb(220, 7, 7)" 
  d="M0.804,15.876 C0.894,15.779 ...中略... L5.942,21.490 Z"/>

auto-reverse

以下は rotate 属性に auto-reverse を指定した場合の例です。auto 同様、モーションパスの方向の角度に自動的に回転させますが180度を加えた角度で回転させます(反転させます)。

<animateMotion 
  xlink:href="#car"
  dur="10s"
  begin="0s"
  fill="freeze"
  rotate="auto-reverse"
  repeatCount="indefinite">
  <mpath xlink:href="#car_mpath" />
</animateMotion>

以下が上記の例の全体のコードです。この例の場合、車のアイコンの初期位置の座標を変更しているので、viewBox のX座標の最小値を-10に変更して表示範囲を調整しています。

<svg width="300" height="250" viewBox="-10 0 300 250">
  <path 
    id="car_mpath" 
    fill="none" 
    stroke="gray" 
    d="M196.722,94.707c16.6-20.633, ...中略... 196.722,94.707Z"/>
  <path 
    id="car" 
    transform="translate(-15, -15.876)" 
    fill="rgb(220, 7, 7)" 
    d="M0.804,15.876 C0.894,15.779 ...中略... L5.942,21.490 Z"/>
  <animateMotion 
    xlink:href="#car"
    dur="10s"
    begin="0s"
    fill="freeze"
    rotate="auto-reverse"
    repeatCount="indefinite">
    <mpath xlink:href="#car_mpath" />
  </animateMotion>
</svg>

<svg width="300" height="250" viewBox="-10 0 300 250">
  <path 
    id="car_mpath" 
    fill="none" 
    stroke="gray" 
    d="M196.722,94.707c16.6-20.633,18.987-47.006-5.073-50.133-8.512-1.106-17.338,3.233-25.887,2.273-7.865-.882-14.472-5.752-20.294-10.738-11.787-10.1-21.127-26.97-38.462-13.772-11.8,8.986-3.825,27.9-16.274,35.631-3.887,2.416-9.285,2.058-13.765,1.82-11.127-.593-19.914-0.444-31.131,2.62C24.843,68.136,18.758,73.947,14.7,85.347c-4.395,12.36,1.418,32.41,16.154,37.389,17.676,5.975,25.961-6.305,45.595.383,16.572,5.641,11.41,19.364,8.749,31.919-5.02,23.683,12.549,37.552,36.126,33.339,7.681-1.374,22.653-5.913,26.958-13.564,3.474-6.175-.757-15.279-1.073-21.73C146.1,130.4,169.849,142.769,184.223,147c13.736,4.046,37.556,8.6,46.222-12.354,2.973-7.189-5.438-23.036-12.228-25.422C208.61,105.852,190.3,102.687,196.722,94.707Z"/>
  <path 
    id="car" 
    transform="translate(-15, -15.876)" 
    fill="rgb(220, 7, 7)" 
    d="M0.804,15.876 C0.894,15.779 1.279,15.495 1.304,15.399 C1.395,15.049 1.496,14.480 1.571,14.015 C2.169,10.123 13.246,3.494 16.337,2.006 C21.485,-0.477 25.955,-0.088 30.704,0.249 C31.631,0.315 32.726,0.377 33.555,0.837 C33.591,0.860 33.625,0.877 33.653,0.899 C34.986,1.593 36.672,3.246 37.578,7.185 C37.717,7.625 37.832,8.076 37.905,8.535 C38.074,9.583 37.988,10.652 38.304,11.677 C38.583,12.582 39.077,13.417 39.288,14.344 C39.378,14.733 40.034,16.683 39.555,17.066 C39.838,17.680 39.997,18.362 39.997,19.080 C39.997,21.796 37.745,23.999 34.969,23.999 C32.668,23.999 30.729,22.401 30.159,20.532 C30.159,20.532 16.076,20.548 10.728,20.548 C10.083,22.547 8.195,23.999 5.942,23.999 C3.649,23.999 1.726,22.502 1.115,20.457 C-0.518,19.758 -0.115,16.890 0.804,15.876 L0.804,15.876 ZM35.397,3.859 C34.514,2.269 33.367,1.213 32.829,1.498 C32.296,1.780 32.575,3.297 33.457,4.891 C34.338,6.479 35.485,7.538 36.023,7.251 C36.560,6.968 36.277,5.448 35.397,3.859 L35.397,3.859 ZM34.969,21.490 C36.328,21.490 37.434,20.408 37.434,19.080 C37.434,17.748 36.328,16.670 34.969,16.670 C33.607,16.670 32.504,17.748 32.504,19.080 C32.504,20.408 33.607,21.490 34.969,21.490 L34.969,21.490 ZM29.106,7.320 C30.159,7.237 31.061,6.322 30.926,5.290 C30.732,3.824 30.180,1.953 28.633,1.514 C27.063,1.067 24.709,1.153 23.060,1.292 C22.006,1.386 20.332,1.758 19.335,2.116 C16.868,3.006 12.505,4.837 10.174,7.374 C9.465,8.144 9.941,8.844 10.994,8.760 L29.106,7.320 ZM5.942,21.490 C7.299,21.490 8.406,20.408 8.406,19.080 C8.406,17.748 7.299,16.670 5.942,16.670 C4.584,16.670 3.477,17.748 3.477,19.080 C3.477,20.408 4.584,21.490 5.942,21.490 L5.942,21.490 Z"/>
  <animateMotion 
    xlink:href="#car"
    dur="10s"
    begin="0s"
    fill="freeze"
    rotate="auto-reverse"
    repeatCount="indefinite">
    <mpath xlink:href="#car_mpath" />
  </animateMotion>
</svg>

テキストをパスに沿って移動

テキストを任意のパスに沿って移動する場合、他の SVG 要素をパスに沿って移動するのとは異なり、animateMotion 要素ではなく animate 要素を使用する必要があります。

パスに沿ってテキストを配置するには、text 要素内に textPath 要素をネストします。

パスに沿って配置されるテキストは textPath 要素内で指定し、textPath 要素で使用するパスを参照します。参照するパスは、実際にレンダリングすることも、defs 内で定義することもできます。

以下は id が text_path の path 要素でレンダリングしたパスに沿って text 要素内にネストした textPath 要素で指定したテキストを表示する例です。

<svg width="300px" height="120px" viewBox="0 0 300 120">
  <path id="text_path" d="M 20,20 C 70 120, 170 120, 260 20" stroke="lightblue" fill="transparent"/>
  <text>
    <textPath href="#text_path" font-size="22px" fill="green">Moving text along a path !</textPath>
  </text>
</svg>
Moving text along a path !

パスに沿ってテキストを移動するアニメーションでは、animate 要素を使用して textPath 要素の startOffset 属性(文字配置の開始位置のオフセット)の値を変化させます。

startOffset はパス上のテキストのオフセットを表し、0%はパスの始まりで、100%はパスの終わりを表します。例えば、オフセットが50%に設定されている場合、テキストはパスの途中から始まります。

textPath 要素の startOffset の値を animate 要素を使って変化させることで、パスに沿って移動するテキストのアニメーションを作成できます。

以下の例では keyTimes 属性calcMode 属性を指定して動きにイージングを適用しています。

<svg width="300px" height="120px" viewBox="0 0 300 120">
  <path id="text_path2" d="M 20,20 C 70 120, 170 120, 260 20" stroke="lightblue" fill="transparent"/>
  <text>
    <textPath href="#text_path2" font-size="22px" fill="green">
      Moving text along a path !
      <animate 
        attributeName="startOffset" 
        from="0%" 
        to ="100%" 
        begin="0s" 
        dur="4s" 
        repeatCount="indefinite" 
        keyTimes="0;1" 
        calcMode="spline" 
        keySplines="0.1 0.2 .22 1"/>
    </textPath>
  </text>
</svg>  
Moving text along a path !
<svg width="300px" height="120px" viewBox="0 0 300 120">
  <path id="text_path3" d="M30,30 h100 v60 h120" stroke="silver" fill="transparent"/>
  <text>
    <textPath href="#text_path3" font-size="16px" fill="red">
      This text moves along a path !
      <animate 
        attributeName="startOffset" 
        values="0%;100%; 0%" 
        begin="0s" 
        dur="8s" 
        repeatCount="indefinite" 
        keyTimes="0;0.5;1" 
        calcMode="spline" 
        keySplines="0.42 0 0.58 1;0.25 0.1 0.25 1"/>
    </textPath>
  </text>
</svg>
This text moves along a path !

animateTransform 要素

animateTransform 要素は変形アニメーション(transform 属性を使ったアニメーション)を定義する要素(SVG 特有の拡張)です。

animateTransform 要素は、対象の要素の transform 属性を変化することにより、アニメーションで移動(translate)、拡大・縮小(scale )、回転(rotate)、およびスキュー・ 傾斜(skewX skewY)を制御できるようにします。

animateTransform 要素では animate 要素で説明したのと同じ属性に加えて、type という追加の属性を取ります。

type 属性は、アニメーションで適用する変換(変形)のタイプを指定するために使用し、translate、scale、rotate、skewX、skewY の5つの値のいずれかを取ります。

type 属性に指定した変換のタイプにより、from、by、to および values 属性に指定する値の形式が異なります(変換タイプで使用できるのと同じ構文を使用)

以下表のタイプの欄のリンクは対応する SVG の属性に関するページへのリンクです。

タイプ 説明(指定する値の形式)
translate
Tx [,Ty]

要素を X 軸または Y 軸に対して指定された距離だけ移動させます。

X、Y座標をカンマまたは半角スペース区切りで指定。Ty(Y座標)が省略された場合、Ty の値は0とみなされます。

scale
Sx [,Sy]

要素を指定された比率で伸縮(拡大・縮小)させます。

X軸方向、Y軸方向の伸縮する比率をカンマまたは半角スペース区切りで指定。Sy が省略された場合は、Sx と同じ値であるとみなされます(同じ比率で伸縮できます)。

rotate
angle [,Cx, Cy]

要素をその原点を中心に時計回りに指定された角度だけ回転させます。

回転角度(angle)と回転の中心のX座標、Y座標を指定。Cx と Cy を省略した場合、SVG キャンバスの左上(0 0)が回転の中心になります。

skewX skewY
skew-angle

skewX() はX軸を基準に、skewY() はY軸を基準に要素に指定された角度の傾斜変換を適用します。

skewX() にはX軸に対する傾斜角度、skewY()にはY軸に対する傾斜角度を指定します。

以下は translate タイプを使って指定した距離を移動するアニメーションの例です。

attributeName 属性で transform を指定して type 属性に translate を指定しています。

values 属性にはX軸方向及びY軸方向に移動する距離を指定しています。

最初の値は 0,0 なので同じ位置で、続いて 100,160 では(120, 180)に移動します。

3つ目の値 260,60 では(280, 80)に移動し、最後の値 0,0 では元の位置(20,20)に戻ります。

<svg width="300" height="200" viewBox="0 0 300 200">
  <circle cx="20" cy="20" r="20" fill="red">
    <animateTransform 
      attributeName="transform" 
      type="translate" 
      dur="3s" 
      repeatCount="indefinite" 
      values="0,0; 100,160; 260,60; 0,0"
      keyTimes="0; 0.5; 0.8; 1"
      calcMode="spline"
      keySplines="0.25 0.1 0.25 1; 
      0 0 0.58 1 ; 
      0.5 0 0.5 1"/>
  </circle>
  <circle cx="20" cy="20" r="3" fill="gold"/>
  <circle cx="120" cy="180" r="3" fill="gold"/>
  <circle cx="280" cy="80" r="3" fill="gold"/>
</svg> 
(20,20) (120,180) (280,80)

以下は正方形とテキストのグループと円を回転する例です。正方形とテキストは g 要素でグループ化して、g 要素にアニメーションを適用しています。

attributeName 属性で transform を指定して type 属性に rotate を指定しています。

g 要素及び circle 要素の animateTransform 要素では from には "0,100,100"、to には "360,100,100" を指定し回転の中心を正方形の中心座標(100,100)として0度から360度まで回転させています。

<svg width="200px" height="200px" viewBox="0 0 200 200">
  <g>
    <rect x="50" y="50" width="100" height="100" fill="lightseagreen"/>
    <text x="65" y="110" font-size="20" fill="white">Rotate</text>
    <animateTransform 
      attributeName="transform" 
      type="rotate" 
      begin="0s" 
      dur="9s" 
      fill="freeze" 
      from="0,100,100" 
      to="360,100,100" 
      repeatCount="indefinite" /> 
  </g>
  <circle cx="50" cy="50" r="10" fill="blue" opacity="0.5">
    <animateTransform 
      attributeName="transform" 
      type="rotate" 
      begin="0s" 
      dur="3s" 
      fill="freeze" 
      from="0,100,100" 
      to="360,100,100" 
      repeatCount="indefinite" /> 
  </circle>
  <circle cx="100" cy="100" r="3" fill="red"/>
</svg>
Rotate

以下は type 属性に scale を指定した拡大・縮小の例です。

scale を使った拡大・縮小では、座標の値もユーザー座標系の原点(0,0)を基準に拡大・縮小されます。

以下は正方形をそれぞれX軸及びY軸方向に2倍にする例です。

水色の正方形は、図形の中心を基準に拡大・縮小するように、正方形の中心が(0,0)になるように元の位置を(-15, -15)にして、translate(215, 30)を適用して初期位置を(200,15)にしています。

また、translate(215, 30) が animateTransform 要素により上書きされないように、additive 属性に sum を指定しています。

<svg width="300" height="200" viewBox="0 0 300 200" style="overflow: visible">
  <rect x="0" y="0" width="30" height="30" fill="pink">
    <animateTransform attributeName="transform" 
      type="scale" 
      values="1,1; 2,2; 1,1;" 
      dur="6s" 
      repeatCount="indefinite" />
  </rect>
  <rect x="60" y="60" width="30" height="30" fill="gold">
    <animateTransform attributeName="transform" 
      type="scale" 
      values="1,1; 2,2; 1,1;" 
      dur="6s" 
      repeatCount="indefinite" />
  </rect>
  <rect x="-15" y="-15" width="30" height="30" transform="translate(215, 30)" fill="lightblue">
    <animateTransform attributeName="transform" 
      type="scale" 
      values="1,1; 2,2; 1,1;" 
      dur="6s" 
      additive="sum"
      repeatCount="indefinite" />
  </rect>
  <rect x="0" y="0" width="30" height="30" fill="transparent" stroke="silver" stroke-dasharray="2"/>
  <rect x="60" y="60" width="30" height="30" fill="transparent" stroke="silver" stroke-dasharray="2"/>
  <rect x="200" y="15" width="30" height="30" fill="transparent" stroke="silver" stroke-dasharray="2"/>
  <circle cx="1" cy="1" r="3" fill="red"/>
  <circle cx="60" cy="60" r="3" fill="orange"/>
  <circle cx="120" cy="120" r="3" fill="orange"/>
  <circle cx="215" cy="30" r="3" fill="blue"/>
</svg>
(0,0) (60,60) (120,120) (215,30)

以下も scale を使った拡大の例です。

ellipse 要素
X軸方向に2倍に拡大しているので、cx の値もその際に2倍の40になります(左端の位置は0)。
circle 要素
X軸方向に2倍に拡大しているので、cx の値もその際に2倍の160になります(左端の位置も60から120)。
車のアイコン(path 要素)

X軸及びY軸方向に2倍に拡大しています。

この path 要素には、translate(200, 0) を適用してX座標を200移動させてあり、元の左端の位置は0なので拡大時でも左端のX座標は同じ位置になります。

また、path 要素に適用した translate(200, 0) が animateTransform 要素により上書きされないように、additive 属性に sum を指定しています。

<svg width="300" height="100" viewBox="0 0 300 100">
  <ellipse cx="20" cy="20" rx="20" ry="20" fill="blue">
    <animateTransform attributeName="transform" 
      type="scale" 
      values="1,1; 2,1; 1,1;" 
      dur="8s" 
      repeatCount="indefinite" />
  </ellipse>
  <circle cx="80" cy="20" r="20" fill="green">
    <animateTransform attributeName="transform" 
      type="scale" 
      values="1,1; 2,1; 1,1;" 
      dur="8s" 
      repeatCount="indefinite" />
  </circle>
  <path fill="red" transform="translate(200, 0)"  
    d="M0,15.876 C0.894,15.779 ...中略... L5.942,21.490 Z">
  <animateTransform attributeName="transform" 
    type="scale" 
    values="1,1; 2,2; 1,1;" 
    dur="8s" 
    additive="sum"
    repeatCount="indefinite" />
  </path>
</svg>
12 24 48 20 40 60 80 120 160 200

g 要素で対象の要素を囲む

scale を使った拡大・縮小の中心はユーザー座標系の原点(0,0)になるので、scale を使って拡大・縮小する場合など、対象の要素を任意の位置に配置する場合、g 要素で対象の要素を囲み、g 要素に translate() を適用して移動するとわかりやすいかも知れません。

以下は g 要素で circle 要素を囲み、circle 要素の中心座標を(0,0)にして g 要素に translate() を適用して移動する例です。

<svg width="120px" height="120px" viewBox="0 0 120 120">
  <g transform="translate(60,60)">
    <circle cx="0" cy="0" r="30" fill="orange">
      <animateTransform
        attributeName="transform"
        type="scale" 
        dur="6s"
        repeatCount="indefinite"
        values="1 2; 2 1; 1 2" />
    </circle>
  </g> 
  <circle cx="60" cy="60" r="3" fill="white"/>
</svg>
(60,60)

複数の変形アニメーションの定義

移動・回転・スケール(拡大・縮小)・スキューは同じ transform 属性なので、複数の変形アニメーションを同時に適用するには additive 属性に "sum" を指定する必要があります(同一属性に複数のアニメーションを定義)。

以下は scale と rotate を使ったアニメーションの例です。

拡大・縮小と回転のどちらも図形の中心を基準にするため、正方形の元の位置を(-10,-10)に配置しています。

左側の正方形は rect 要素自体に translate() を適用し、右側の正方形は g 要素で rect 要素を囲み、g 要素に translate() を適用しています。

g 要素に適用した translate() は、rect 要素に適用している animateTransform で上書きされないので、右側(2つ目)の正方形の最初の animateTransform への additive="sum" は必要ありません。

<svg width="200px" height="100px" viewBox="0 0 200 100">
  <rect x="-10" y="-10" width="20" height="20" transform="translate(60, 60)" fill="mediumpurple" opacity="0.5">
    <animateTransform 
      attributeName="transform" 
      type="scale" 
      begin="0s" 
      dur="3s" 
      fill="freeze" 
      values="1,1; 3,3; 1,1;" 
      additive="sum"
      repeatCount="indefinite" />
    <animateTransform 
      attributeName="transform" 
      type="rotate" 
      begin="0s" 
      dur="2s" 
      fill="freeze" 
      from="0,0,0" 
      to="360,0,0" 
      additive="sum"
      repeatCount="indefinite" />
  </rect>
  <circle cx="60" cy="60" r="3" fill="purple"/>
  
  <g transform="translate(140, 60)">
    <rect x="-10" y="-10" width="20" height="20" fill="green" opacity="0.5">
      <animateTransform 
        attributeName="transform" 
        type="scale" 
        begin="0s" 
        dur="3s" 
        fill="freeze" 
        values="1,1; 3,3; 1,1;" 
        repeatCount="indefinite" />
      <animateTransform 
        attributeName="transform" 
        type="rotate" 
        begin="0s" 
        dur="2s" 
        fill="freeze" 
        from="360,0,0" 
        to="0,0,0" 
        additive="sum"
        repeatCount="indefinite" />
    </rect>
  </g>
  <circle cx="140" cy="60" r="3" fill="green"/>
</svg>
(60,60) (140,60)

以下は translate と rotate を使ったアニメーションの例です。

複数の変形アニメーションを同時に適用するので additive="sum" を指定しています。

また、回転のアニメーションには calcMode 属性に spline を指定して keySplines 属性でイージングを適用しています。

<svg width="300px" height="150px" viewBox="0 0 300 150">   
  <rect x="20" y="20" width="40" height="40" fill="red">
    <animateTransform
      attributeName="transform" 
      type="translate" 
      values="0,20; 120,80; 240,20; 0,20"
      dur="6s" 
      repeatCount="indefinite"
      additive="sum" />
    <animateTransform
      attributeName="transform" 
      type="rotate" 
      from="0 40,40" 
      to="360 40,40"
      dur="1s" 
      repeatCount="indefinite"
      calcMode="spline"
      keyTimes="0;1"
      keySplines="0.25 0.1 0.25 1"
      additive="sum" />
  </rect>
</svg> 

以下は skewX と skewY を使ったアニメーションの例です。

scale() 同様、スキュー操作も中心はユーザー座標系の原点(0,0)になるで、以下の例では正方形の中心が(0,0)になるように x="-50" y="-50" を指定して、rect 要素を囲んでいる g 要素に translate(100,100) を適用して、x="50" y="50" に配置しています。

<svg width="200px" height="200px" viewBox="0 0 200 200">
  <rect x="50" y="50" width="100" height="100" fill="gold" />
  <g transform="translate(100,100)">
    <rect x="-50" y="-50" width="100" height="100" fill="blue" fill-opacity="0.5">
      <animateTransform
         id="animateTransform1" 
         attributeName="transform"
         type="skewX" 
         dur="6s"
         begin="0s; animateTransform2.end"
         values="0; 45; -45; 0" />
      <animateTransform
         id="animateTransform2" 
         attributeName="transform"
         type="skewY" 
         dur="6s"
         begin="animateTransform1.end"
         values="0; 45; -45; 0" />
    </rect>
  </g>
  <circle cx="100" cy="100" r="3" fill="red"/>
</svg>
(100,100)

複数の変形アニメーションの定義(rotate と scale)

以下は rect 要素で定義した正方形に transform 属性の rotate と scale の変形処理を適用した図形です。

複数の変形処理を指定した場合、図形に適用される変形処理は右側にある関数から適用されます。

<svg width="200px" height="200px" viewBox="0 0 200 200">
  <rect x="50" y="50" width="50" height="50" fill="lightseagreen" transform="scale(1.41,.81) rotate(45 75 75)" />
</svg>  

上記の変形処理をアニメーションで行う場合、以下のように記述しても同じ結果にはなりません。

<svg width="200px" height="200px" viewBox="0 0 200 200">
  <rect x="50" y="50" width="50" height="50" fill="lightseagreen">
    <animateTransform
      id="rotate1"
      attributeName="transform"
      type="rotate" 
      dur="1s"
      begin="click" 
      fill="freeze"
      additive="sum" 
      values="0 75 75; 45 75 75" />
    <animateTransform
      attributeName="transform"
      type="scale" 
      dur="2s"
      begin="rotate1.end" 
      additive="sum" 
      values="1,1; 1.41,.81; 1,1" />
  </rect>   
</svg>

クリックするとアニメーションが開始します。

rect 要素に scale を適用する際のアニメーションが、回転した角度の効果が無視されて単純に長方形の縦横が伸縮してしまいます。

この場合、以下のように rotate のアニメーションを適用した rect 要素を g 要素で囲んで、g 要素に scale のアニメーションを適用すると期待通りの動作になります。

<svg width="200px" height="200px" viewBox="0 0 200 200">
  <g>
    <rect x="50" y="50" width="50" height="50" fill="lightseagreen">
      <animateTransform
        id="rotate2"
        attributeName="transform"
        type="rotate" 
        dur="1s"
        begin="click" 
        fill="freeze"
        additive="sum" 
        values="0 75 75; 45 75 75" />
    </rect>
    <animateTransform
      attributeName="transform"
      type="scale" 
      dur="2s"
      begin="rotate2.end"
      additive="sum"               
      values="1,1; 1.41,.81; 1,1" />
  </g>   
</svg>

以下は、skewY、translate、rotate、scale を使ったアニメーションの例です。

重なった3つの rect 要素を最終的に以下のような図形にアニメーションさせる例です。

以下の図形は css-tricks.com:Use and Reuse Everything in SVG を参考にさせていただきました。

<svg width="160px" height="120px" viewBox="0 0 80 60">
  <defs>
    <g id="cube0" class="cube-unit">
      <rect width="21" height="24" fill="#73CC51" stroke="#348315" 
        transform="skewY(30)" opacity="0.8"/>
      <rect width="21" height="24" fill="#286411" stroke="#348315" 
        transform="skewY(-30) translate(21 24.3)" opacity="0.8"/>
      <rect width="21" height="21" fill="#4DBC22" stroke="#348315" 
        transform="scale(1.41,.81) rotate(45) translate(0 -21)" opacity="0.8"/>
    </g>
  </defs>
  <use href="#cube0" x="20" y="20"/>
</svg>

3つの rect 要素は g 要素でグループ化して def 要素内で定義して、use 要素で表示しています。

3つ目の rect 要素は、scale の処理が期待通りに動作するように g 要素で囲んで scale を適用しています。

<svg width="160px" height="120px" viewBox="0 0 80 60">
  <defs>
    <g id="cube">
      <rect width="21" height="24" fill="#73CC51" stroke="#348315" opacity="0.8">
        <animateTransform
          id="cube_animate1" 
          attributeName="transform"
          type="skewY" 
          dur="1s"
          begin="cube_rect3.click; use_cube.click"
          restart="never"
          fill="freeze"
          values="0; 30" />
      </rect>
      
      <rect width="21" height="24" fill="#286411" stroke="#348315" opacity="0.8">
        <animateTransform
          id="cube_animate2" 
          attributeName="transform"
          type="translate" 
          dur="1s"
          begin="cube_animate1.end"
          fill="freeze"
          additive="sum"               
          values="0 0; 21 12.15" />
        <animateTransform
          id="cube_animate3" 
          attributeName="transform"
          type="skewY" 
          dur="1s"
          begin="cube_animate2.end"
          fill="freeze"
          additive="sum"               
          values="0; -30" />
      </rect>
      
      <g id="cube_rect3">
        <rect width="21" height="24" fill="#4DBC22" stroke="#348315" opacity="0.8">
          <animate 
            id="cube_animate4" 
            attributeName="height"
            from="24"
            to="21" 
            dur="0.5s"
            begin="cube_animate3.end"
            fill="freeze" />
          <animateTransform
            id="cube_animate5" 
            attributeName="transform"
            type="translate" 
            dur="1s"
            begin="cube_animate4.end"
            fill="freeze"
            additive="sum"               
            values="0 0; 0 -21" />
          <animateTransform
            id="cube_animate6" 
            attributeName="transform"
            type="rotate" 
            dur="1s"
            begin="cube_animate5.end"
            fill="freeze"
            additive="sum"               
            values="0; 45 0 21" />
        </rect>
        <animateTransform
          id="cube_animate7" 
          attributeName="transform"
          type="scale" 
          dur="1s"
          begin="cube_animate6.end"
          fill="freeze"
          additive="sum"               
          values="1,1; 1.41,.81" />
      </g>
    </g>
  </defs>
  <use d="use_cube" href="#cube" x="20" y="20"/>
</svg>

クリックするとアニメーションが開始されます。

restart 属性に "never" を指定しているため、アニメーションを再開するにはページを再読み込みする必要があります。但し、Safari では restart="never" が無視されるようで、アニメーションが再開されてしまいます(再開されるような作りになっていないため、2度目以降のクリックではおかしなアニメーションになってしまいます)

また、Firefox の場合、begin 属性に設定してある cube_rect3.click ではアニメーションが開始されないため、use 要素に id を指定して use_cube.click を追加しないと開始されませんでした。

以下は前述の例に、元に戻るアニメーションを追加したものです。

クリックするとアニメーションが開始されます。こちらも restart="never" を指定しているため、アニメーションを再開するにはページを再読み込みする必要があります(こちらも前述の例同様、Safari では restart="never" の指定が無視されます)。

また、Firefox の場合、begin 属性に設定してある cube_rectx3.click と use_cubex.click ではアニメーションが開始されないため、svg 要素に id を指定して svg_cube_animation2.click を追加しないと開始されませんでした。。。

もっと効率的な方法があるかも知れません。

<svg width="160px" height="120px" viewBox="0 0 80 60" id="svg_cube_animation2">
  <defs>
    <g id="cubex">
      <rect width="21" height="24" fill="#73CC51" stroke="#348315" opacity="0.8">
        <animateTransform
          id="cube_animatex1" 
          attributeName="transform"
          type="skewY" 
          dur="1s"
          begin="cube_rectx3.click; use_cubex.click; svg_cube_animation2.click"
          restart="never"
          fill="freeze"
          values="0; 30" />
        <animateTransform
          id="cube_animatex14" 
          attributeName="transform"
          type="skewY" 
          dur="1s"
          begin="cube_animatex13.end"
          fill="freeze"
          values="30; 0" />
      </rect>
      
      <rect width="21" height="24" fill="#286411" stroke="#348315" opacity="0.8">
        <animateTransform
          id="cube_animatex2" 
          attributeName="transform"
          type="translate" 
          dur="1s"
          begin="cube_animatex1.end"
          fill="freeze"
          additive="sum"               
          values="0 0; 21 12.15" />
        <animateTransform
          id="cube_animatex13" 
          attributeName="transform"
          type="translate" 
          dur="1s"
          begin="cube_animatex12.end"
          fill="freeze"
          additive="sum"               
          values="0 0; -21 -12.15" />
        <animateTransform
          id="cube_animatex3" 
          attributeName="transform"
          type="skewY" 
          dur="1s"
          begin="cube_animatex2.end"
          fill="freeze"
          additive="sum"               
          values="0; -30" />
        <animateTransform
          id="cube_animatex12" 
          attributeName="transform"
          type="skewY" 
          dur="1s"
          begin="cube_animatex11.end"
          fill="freeze"
          additive="sum"               
          values="0; 30" />
      </rect>
      
      <g id="cube_rectx3">
        <rect width="21" height="24" fill="#4DBC22" stroke="#348315" opacity="0.8">
          <animate 
            id="cube_animatex4" 
            attributeName="height"
            from="24"
            to="21" 
            dur="0.5s"
            begin="cube_animatex3.end"
            fill="freeze" />
          <animate 
            id="cube_animatex11" 
            attributeName="height"
            from="21"
            to="24" 
            dur="0.5s"
            begin="cube_animatex10.end"
            fill="freeze" />
          <animateTransform
            id="cube_animatex5" 
            attributeName="transform"
            type="translate" 
            dur="1s"
            begin="cube_animatex4.end"
            fill="freeze"
            additive="sum"               
            values="0 0; 0 -21" />
          <animateTransform
            id="cube_animatex10" 
            attributeName="transform"
            type="translate" 
            dur="1s"
            begin="cube_animatex9.end"
            fill="freeze"
            additive="sum"               
            values="0 0; 0 21" />
          <animateTransform
            id="cube_animatex6" 
            attributeName="transform"
            type="rotate" 
            dur="1s"
            begin="cube_animatex5.end"
            fill="freeze"
            additive="sum"               
            values="0; 45 0 21" />
          <animateTransform
            id="cube_animatex9" 
            attributeName="transform"
            type="rotate" 
            dur="1s"
            begin="cube_animatex8.end"
            fill="freeze"
            additive="sum"               
            values="0; -45 0 21" />
        </rect>
        <animateTransform
          id="cube_animatex7" 
          attributeName="transform"
          type="scale" 
          dur="1s"
          begin="cube_animatex6.end"
          fill="freeze"
          additive="sum"               
          values="1,1; 1.41,.81" />
        <animateTransform
          id="cube_animatex8" 
          attributeName="transform"
          type="scale" 
          dur="1s"
          begin="cube_animatex7.end"
          fill="freeze"
          additive="sum"               
          values="1,1; 0.7092198,1.2345679" />
      </g>
    </g>
  </defs>
  <use d="use_cubex" href="#cubex" x="20" y="20"/>
</svg>