SVGにはアフィン変換が可能なプロパティが存在します。transform
という属性でこれを利用することで以下の要素に線形な座標変換を行うことが可能です。少々ニッチかもしれないですが今回はこのアフィン変換を利用して簡単にアニメーションする方法をご紹介します。
アフィン変換の行列表記
平面におけるアフィン変換は行列$B$,$\mathbf{s}$を用いて以下のように表せます。
\[ B = \begin{pmatrix} a & c \\ b & d \end{pmatrix} \quad \tilde{\mathbf{z}} = \begin{pmatrix} \tilde{x} \\ \tilde{y} \end{pmatrix} \quad \mathbf{z} = \begin{pmatrix} x \\ y \end{pmatrix} \quad \mathbf{s} = \begin{pmatrix} e \\ f \end{pmatrix} \]
\[ \tilde{\mathbf{z}} = B\mathbf{z} + \mathbf{s} \]
ただし、変換前の座標を$\mathbf{s}$、変換後の座標を$\tilde{\mathbf{z}}$としています。このようにアフィン変換は$B,\mathbf{s}$なる6つの実数パラメータによって決まる、座標変換であると捉えることができます。(ちなみに$\mathbf{s}=0$の場合は線形変換と呼ばれます。)
ただ、このままの状態では扱いづらいことが多いため、上記の式は一つの行列にまとめられることが多いです。この場合、以下のように記述することができます。
\[ A = \begin{pmatrix} a & c & e \\ b & d & f \\ 0 & 0 & 1 \end{pmatrix} \quad \tilde{\mathbf{x}} = \begin{pmatrix} \tilde{x} \\ \tilde{y} \\ 1 \end{pmatrix} \quad \mathbf{x} = \begin{pmatrix} x \\ y \\ 1 \end{pmatrix} \]
\[ \tilde{\mathbf{x}} = A\mathbf{x} \]
ただし、変換前の座標を$\mathbf{x}$、変換後の座標を$\tilde{\mathbf{x}}$としています。このように、正方行列を用いて記述すると逆変換が逆行列によって定義できるなど、非常に扱いやすくなります。以下ではこの行列$A$を変換行列と呼ぶことにします。
各種変換における変換行列
SVGにはアフィン変換の分類として移動(translate
)、拡大縮小(scale
)、回転(rotate
)、せん断(skewX
/skewY
)があります。これらと変換行列の対応は
あたりがわかりやすいのでこちらを参考にしてください。
変換行列について、各種行列演算との関係についても補足しておきましょう。複数の変換の合成は行列積によって表現されます。また、逆変換は逆行列です。さらに行列で表現されることから、結合法則も成立しています。もちろん、変換順序の入れ替えはできないので注意してください。
複数回の変換は行列積によってひとまとめにできることから、以下では変換行列を一つとして考えます。
点の移動から変換行列を求める
$\mathbf{x_1},\mathbf{x_2},\mathbf{x_3}$がそれぞれ$\tilde{\mathbf{x_1}},\tilde{\mathbf{x_2}},\tilde{\mathbf{x_3}}$に変換されたとしましょう。このとき、変換行列$A$を用いて、
\[ \begin{pmatrix} \tilde{\mathbf{x_1}} & \tilde{\mathbf{x_2}} & \tilde{\mathbf{x_3}} \end{pmatrix} = A \begin{pmatrix} \mathbf{x_1} & \mathbf{x_2} & \mathbf{x_3} \end{pmatrix} \]
と書くことができます。よって、 \[ \begin{pmatrix} \tilde{\mathbf{x_1}} & \tilde{\mathbf{x_2}} & \tilde{\mathbf{x_3}} \end{pmatrix} \begin{pmatrix} \mathbf{x_1} & \mathbf{x_2} & \mathbf{x_3} \end{pmatrix}^{-1} = A \] となります。ちなみに$(\mathbf{x_1},\mathbf{x_2},\mathbf{x_3})$が正則であることと3点が同一直線上にないことは同値(たぶん)です。つまり、任意の変換行列は3点の変換先がわかれば計算できるということが分かります。
アニメーションする
変換行列が計算できたらあとは変換途中の点を補完してやればOKです。$0\leq p \leq 1$として$p=0$を変換前、$p=1$を変換後とすれば以下のように表現できます。($E$は単位行列)
\[ A(p) = (1-p)E + pA_\text{end} \]
時間$t(0\leq t \leq t_0)$と$p$の関係は自由に定めると良いでしょう。$p=\sin{\frac{\pi t}{2t_0}}$などと定めればゆっくりスタートして加速後、また遅くなるといった動きが実現できると思います。
このようにして計算された変換行列はtransform
属性のmatrix
などを用いることで適応することが可能です。このようにすればアフィン変換をベースとしたアニメーションが比較的簡単で機械的に作成できます。