SVGのanimateTransform要素は、その親要素をアニメーションさせながら変形したり動かしたりするためのもの。fromto要素だけでもちょっとしたことならできるけど、複雑なことをやるにはvalueskeyTimes属性とを組み合わせるようだ。

Move 300px in 2s, Sleep 2s, Move -300px in 2s, Sleep 2s

均等にシーンを割り当てる場合はvalues属性を書くだけで良い。

<animateTransform
  attributeName="transform"
  attributeType="XML"
  begin="0s"
  dur="8s"
  repeatCount="indefinite"
  values="0; 300; 300; 0; 0"
  type="translate"/>

values属性に指定した値の個数から1を引いた数でdur属性の値が均等に割られ、割り当てられる。

Move 300px in 3s, Sleep 1s, Move -300px in 3s, Sleep 1s

シーンへの割り当てが偏る場合はvalues属性にkeyPoints属性でタイミングを割り当てる。

<animateTransform
  attributeName="transform"
  attributeType="XML"
  begin="0s"
  dur="8s"
  repeatCount="indefinite"
  values="0; 300; 300; 0; 0"
  keyTimes="0; 0.375; 0.5; 0.875; 1"
  type="translate"/>

keyTimes属性ではdur属性の値を1とした相対的な数値でvalues属性と同じ数だけ刻む。

Jump 75px in 1s * 4, Jump -75px in 1s *4

calcMode="discrete"にするとアニメーション過程が省略される。

<animateTransform
  attributeName="transform"
  attributeType="XML"
  begin="0s"
  dur="8s"
  repeatCount="indefinite"
  calcMode="discrete"
  values="0; 75; 150; 225; 300; 225; 150; 75; 0"
  type="translate"/>

ここではtranslateに対してdiscreteなのでジャンプしているように見える。

Move 150px in 3s, Jump 150px, Sleep in 1s, Move -150px in 3s, Jump -150px, Sleep in 1s

アニメーションとジャンプを混ぜる場合はkeyTimes属性を同じタイミングで刻むだけで良い。ジャンプのみの場合もkeyTimes属性を使う方がdiscreteを使うより簡単かもしれない。

<animateTransform
  attributeName="transform"
  attributeType="XML"
  begin="0s"
  dur="8s"
  repeatCount="indefinite"
  values="0; 150; 300; 300; 150; 0; 0"
  keyTimes="0; 0.375; 0.375; 0.5; 0.875; 0.875; 1"
  type="translate"/>

移動するアニメーションとジャンプするアニメーションを別々に作り、endイベントを使ってチェーンさせるという手もあるけど、同じtranslateのアニメーションならまとめた方が書きやすい。


これにアニメーション自体のタイミングが加わることになるので、手で書くのはこれくらいが限界な気がする。そこへ行くとCSS TransitionsCSS Animationsは書きやすい実装なんだな、と思った。