読者です 読者をやめる 読者になる 読者になる
このブログは http://abicky.net に移行しました。近い将来こちらの記事は移行先のリンクのみになる予定です。

HTML5 の Canvas で getTransform が使えるようにしてみた

CanvasRenderingContext2D には setTransform があるのに getTransform はありません。
transform, rotate, save, restore などを駆使して変換しまくってると、現在どのような変換行列が適用されているのかよくわからなくなり、表示が乱れていてもデバッグしにくいこと極まりないです。
実際、「canvas gettransform」でググると「getTransform 欲しいよね」とか、「どうやったら現在の変換行列の状態が取得できるか?」とか、出てきます。その割に誰も getTransform を実装している気配がありません。


というわけで実装してみました。
------ 2012-07-24 追記 --------
行列の掛け算が逆になっているという悲惨な状態だったので修正しました。ご指摘ありがとうございます。


このスクリプトをロードすることで CanvasRenderingContext2D#getTransform が使えるようになります。
現在の変換行列の状態を長さ6の配列で返します。配列の各要素の順番は CanvasRenderingContext2D#setTransform の引数の順番に対応しています。


サンプル

こちらのサンプルを拝借して途中の変換行列の状態を表示してみます。

<html>
<head>
<script type="text/javascript" src="canvas_get_transform.js"></script>
<script type="text/javascript">
function draw() {
    var ctx = document.getElementById('canvas').getContext('2d');
    ctx.translate(75,75);

    for (var i=1;i<6;i++){ // Loop through rings (from inside to out)
        ctx.save();
        ctx.fillStyle = 'rgb('+(51*i)+','+(255-51*i)+',255)';

        for (var j=0;j<i*6;j++){ // draw individual dots
            ctx.rotate(Math.PI*2/(i*6));
            ctx.beginPath();
            ctx.arc(0,i*12.5,5,0,Math.PI*2,true);
            ctx.fill();
            console.log(ctx.getTransform());
        }
        ctx.restore();
    }
}
</script>
</head>
<body onload="draw()">
</body>
<canvas id="canvas"></canvas>
</html>


表示結果は次のようになります。


・・・パッと見ても合ってるのか間違ってるのかよくわかりませんが、とりあえず変換行列の状態が取得できてるっぽいです。



精度の問題で微妙にずれたり、canvas のサイズをいじった時のことを考慮できてなかったりしますが、デバッグ用途としてはそれなりに機能するのではないでしょうか。


というわけで、よかったらお使いください!