サイト内検索

transform() メソッド

構文

context . transform(m11, m12, m21, m22, dx, dy)

下記の通りに引数に指定されたマトリックスを適用して、変換マトリックスを変更します。

仕様

変換マトリックスは、図形やパスが生成されるときに座標に適用されます。

コンテキストが生成されると、変換マトリックスは恒等変換で初期化されます。変形メソッドを使うことによって、変換マトリックスを調整することができます。

変形は、逆の順番で実行されなければいけません。たとえば、幅を2倍にする伸張変形を適用し、続いて、90°の回転変形を適用し、そして、canvas上に幅が高さの2倍となる矩形を描画すると、その実際の結果は、正方形となります。

transform(m11, m12, m21, m22, dx, dy) メソッドは、現在の変換マトリックスを次のマトリックスで掛けあわせなければいけません:

m11 m21 dx
m12 m22 dy
0 0 1

原文:http://www.w3.org/TR/2010/WD-2dcontext-20100624/#dom-context-2d-transform

サンプル

transform() メソッドは、一度セットされると、それ以降に描かれる図形はすべてその変換マトリックスが適用されます。transform() メソッドで変換マトリックスを定義したあとに、別の変換マトリックスを transform() メソッドで定義すると、2つの変換マトリックスを掛け合わせた変換マトリックスが適用された状態となります。

もし、新たな変換マトリックスを適用したい場合は、setTransform() メソッドで変換マトリックスを定義しなければいけないことに注意してください。

では、まず setTransform() メソッドの使い方をみていきましょう。

setTransform() メソッドの例

setTransformメソッドのサンプル

このサンプルは、まず赤色で矩形を描いています。次に元の図形を右に 45° 回転したものを青色で描いています。次に元の図形を 2.5 倍に拡大したものを緑色で描いています。最後に、元の図形を右下に移動したものを灰色で描いています。

/* ----------------------------------------------
* 元の矩形を赤色で描く
* -------------------------------------------- */
ctx.strokeStyle = "red";
ctx.strokeRect(30, 10, 60, 20);

/* ----------------------------------------------
* 45°回転した矩形を青色で描く
* -------------------------------------------- */
/* 45°をラジアンに変換 */
var rad = 45 * Math.PI / 180;
/* 右に45°回転する変換マトリックスを定義 */
ctx.setTransform(Math.cos(rad), Math.sin(rad), -Math.sin(rad), Math.cos(rad), 0, 0 );
/* 図形を描画 */
ctx.strokeStyle = "blue";
ctx.strokeRect(30, 10, 60, 20);

/* ----------------------------------------------
* 2.5倍に拡大したものを緑色で描く
* -------------------------------------------- */
/* 2.5倍の拡大する変換マトリックスを定義 */
ctx.setTransform(2.5, 0, 0, 2.5, 0, 0);
/* 図形を描画 */
ctx.strokeStyle = "green";
ctx.strokeRect(30, 10, 60, 20);

/* ----------------------------------------------
* 右に40、下に80だけ移動したものを灰色で描く
* -------------------------------------------- */
/* 右に40、下に80だけ移動する変換マトリックスを定義 */
ctx.setTransform(1, 0, 0, 1, 40, 80);
/* 図形を描画 */
ctx.strokeStyle = "gray";
ctx.strokeRect(30, 10, 60, 20);
        

[setTransform() メソッドの実際のサンプル]

Canvas では、変換マトリックスを適用すると、左上端、つまり座標 (0,0) の地点を中心とした変換が行われます。

transform() メソッドの例

transformメソッドのサンプル

transform() メソッドを繰り返し適用すると、setTransform() メソッドで初期化されない限り、それまでの変換マトリックスが掛け合わされていきます。この特定を利用して、簡単な虹を描いてみましょう。

/* 色の定義(赤、橙、黄、緑、青、藍、紫) */
var colors = ["red", "orange", "yellow", "green", "blue", "navy", "purple"];
/* 線の太さをセット */
ctx.lineWidth = 10;
/* 円弧を繰り返し描画 */
for( var i=0; i<colors.length; i++ ) {
  /* 下に10だけ移動する変換マトリックスを定義 */
  ctx.transform(1, 0, 0, 1, 0, 10);
  /* 色をセット */
  ctx.strokeStyle = colors[i];
  /* 円弧を描画 */
  ctx.beginPath();
  ctx.arc(50, 100, 100, 0, Math.PI, true);
  ctx.stroke();
}

[transform() メソッドの実際のサンプル]

このサンプルでは、arc() メソッドを使って、常に同じ位置に円弧を描こうとしている点に注目してください。しかし、arc() メソッドを実行する前に、transform() メソッドで下方に 10 ピクセルだけ移動する変換マトリックスを適用しているため、10 ピクセルずつ下方にずれながら描画されていきます。

複雑な変換

これまで紹介したサンプルは、わざわざ使いにくい transform() メソッド や setTransform() メソッドを使う必要はありません。図形の移動であれば translate() メソッドを、図形の回転であれば rotate() メソッドを、図形の倍率変換であれば scale() メソッドで事足ります。

transform() メソッドや setTransform() メソッドはもう少し複雑な変換を適用したい場合に、本領を発揮します。ここでは、Canvas の図形平面を立体的に斜めに傾けたように見せるサンプルをご覧頂きます。このサンプルは 1 秒おきに時間を刻むアニメーションとして作られています。Firefox 3.0 以上、Safari 3.1 以上、または、Opera 9.5 以上でご覧ください。

[時計のアニメーションの実際のサンプル]

変換前の図形 返還後の図形

左側の図は変換前の図形です。そして右側の図は transform() メソッドで変換した図形です。JavaScript では、事前に transform() メソッドで座標空間変換をセットしておきます。そして左側の図を中心が座標 (0,0) に位置するように描きます。すると、右側の図の通りに描画されます。このサンプルで使った座標変換は以下の通りです。

ctx.transform(0.8, -0.2, -0.3, 0.8, g.x, g.y);

g.xg.y は Canvas の中心位置の座標です。

このサンプルは、文字盤に PNG 画像を使い、針を直線で描いたものです。ご覧の通り、組み込まれた画像、path を使って描いた図形、背景のグラデーションすべての座標空間が変換されています。

Canvas 上に、座標空間を立体的に斜めに傾けた図を描くのは非常に困難です。傾ける前の図形を Canvas に描く方がはるかに簡単です。事前に transform() メソッドや setTransform() メソッドを使って座標空間変換をセットしておくだけで、このような立体的な傾きなどを再現できるのです。

ブラウザ対応状況

Firefox Safari Chrome Opera IE ExplorerCanvas
2 × 2 × 1 ○ 9.2 × 9 ○ 0002 ×
3 ○ 3 ○ 2 ○ 9.5 ○   3 ○
3.5 ○ 4 ○ 3 ○ 10 ○    
3.6 ○ 5 ○ 6 ○ 10.60 ○    

Safari3とChrome 1 では、transform メソッドは実装されていますが、setTransform() メソッドは実装されていません。そのため、本ページのサンプルで setTransform() メソッドを使ったものについては、Safari 3 と Chrome 1 では動作しません。