矩形を回転させるの巻。
Canvasでのオブジェクトの移動や回転はめんどい。
FlashのDisplayObjectを回転させるのに慣れているとなんでこんなに面倒なのかとぼやきたくなる。
まず描画した矩形を回転させるのではなく、回転しているのは描画のもとCanvasそのものだと考えるようにしました。
HTML
<canvas id='canvas'></canvas> |
JavaScript
var canvas = document.getElementById('canvas'); var context = canvas.getContext('2d'); context.save(); context.fillStyle = '#0000ff'; context.fillRect(100,100,50,50); context.setTransform(1,0,0,1,0,0); var radian = 45 * Math.PI / 180; context.rotate(radian); context.fillStyle = '#ff0000'; context.fillRect(100,100,50,50); context.fillStyle = '#00ff00'; context.fillRect(200,200,50,50); context.restore(); |
rotate後にfillRectした矩形は思いもよらないところに描かれてしまいます。
save, restore
saveは現在の状態を保存し、restoreで復元します。
データは配列状態で保存されるようでsaveでpushされrestoreでshiftされるみたいです。
なんかめんどくさい。
setTransformはActionScriptのMatrixに相当するものだと思います。
回転させる前にsetTransformで定義してrotateするのかな。
上記のコードでsave, restoreを使わないときはrestoreの所を次のようにすれば同じ結果になります。
context.setTransform(1,0,0,1,0,0); |
context.rotate(0);
context.rotate(0);
は必要ない。
後から描く赤い矩形を座標[100, 100]で回転させるには少々工夫が必要になります。
var canvas = document.getElementById('canvas'); var context = canvas.getContext('2d'); context.save(); context.fillStyle = '#0000ff'; context.fillRect(100,100,50,50); context.setTransform(1,0,0,1,0,0); var radian = 45 * Math.PI / 180; var x=100,y=100,w=50,h=50; context.translate(x+0.5*w,y+0.5*h); context.rotate(radian); context.fillStyle = '#ff0000'; context.fillRect(-0.5*w,-0.5*h,w,h); context.restore(); |
translateを使い移動させて回転させる。
ActionScriptでMatrixを使い中心点に関係なく回転させるやり方と同じ。
【回転】
Canvas state 保存
tarnsformation Matrixを初期化(identity)する, context.setTransform(1,0,0,1,0,0);
translateで移動
rotateで回転
fillRect座標を矩形の幅と高さの半分をネガティブ側へオフセットさせて描く
Canvas state 復元
【Matrix】関連関数
translate: 移動, rotate: 回転以外にscale: 拡大・縮小が用意されている。
【参考資料】
W3C: http://www.w3.org/TR/2010/WD-2dcontext-20100624/#transformations
MatrixはAdobeのActionScrit 3.0 リファレンスガイドが詳しい。
Matrix
update 2012-04-27
複数の矩形を回転させてみた。
var canvas = document.getElementById('canvas'); var context = canvas.getContext('2d'); var x=20,y=20,w=50,h=50, r=15; function circle (x, y) { var r = 10; context.beginPath(); context.arc(x+r, y+r, r, (Math.PI/180)*0, (Math.PI/180)*360, false); context.fillStyle = 'yellow'; context.fill(); context.closePath(); context.fillStyle = 'rgba(255,0,0,0.5)'; } context.fillStyle = '#0000ff'; context.fillRect(x,y,w,h); circle(x, y); context.setTransform(1,0,0,1,0,0); var radian = 45 * Math.PI / 180; context.translate(x+0.5*w,y+0.5*h); context.rotate(radian); context.fillStyle = 'rgba(255,0,0,0.5)'; context.fillRect(-0.5*w,-0.5*h,w,h); circle(-0.5*w,-0.5*h); context.setTransform(1,0,0,1,0,0); x += 100; context.translate(x+0.5*w,y+0.5*h); context.rotate(90 * Math.PI / 180); context.fillRect(-0.5*w,-0.5*h,w,h);; circle(-0.5*w,-0.5*h); context.setTransform(1,0,0,1,0,0); x += 100; context.translate(x+0.5*w,y+0.5*h); context.rotate(135 * Math.PI / 180); context.fillRect(-0.5*w,-0.5*h,w,h); circle(-0.5*w,-0.5*h); context.setTransform(1,0,0,1,0,0); x += 100; context.translate(x+0.5*w,y+0.5*h); context.rotate(180 * Math.PI / 180); context.fillRect(-0.5*w,-0.5*h,w,h); circle(-0.5*w,-0.5*h); context.setTransform(1,0,0,1,0,0); |
ピンバック: Canvas始めました - Canvas APIで遊んで(遊ばれて)わかったことをだらだらと « イナヅマtvログ