お寿司か焼き肉食べたい

まじめな事からしょーもない事まで
めにゅーを開く(投げやり)

ガシャーンガシャーン変形

transform CSS3でもお世話になったヤツ
使い方も一緒なのがありがたいですね。
ちなみに先に言っときますが、最後のパスが参照されるこれは基本として覚えといてくださいね

transformを使用する前に大切な約束

実は、描画後に効果がないのです。
基本的に、パス指定→transform→描画の流れです

で、後述しますが、あれこれ変形させますが、組み合わせる時は順序に注意してください。
例えば、[拡大して回転して拡大] と [拡大して拡大して回転]は別の結果になることがあるのです
この辺は後でやってますのでそっちを参照してください。

context.scale(x, y)

拡大縮小 XはX軸方向への伸縮倍率 YはY軸方向への伸縮倍率を記述します。

var canvas1 = document.getElementById('canvas01');
canvas1.width = 200;
canvas1.height = 200;
if (canvas1.getContext) {
  var context1 = canvas1.getContext('2d');
  // 新しいパスを開始する
  context1.beginPath();

  // 四角の生成
  context1.rect(30, 50, 70, 70);

  // 縦方向に2倍
  context1.scale(1,2); 

  // 四角の生成
  context1.rect(50, 10, 70, 70);

  // 塗りつぶし背景色の設定
  context1.fillStyle = '#ddd';

  // 塗りつぶし
  context1.fill();

  // 輪郭線の描画
  context1.stroke();
}

context.rotate()

回転です。
回転はラジアンで指定しますので、いつもの数式で算出してあげましょう。
ちなみにrotateした後にrotateは前回rotate値からの計算になるのでご注意ください。

var canvas2 = document.getElementById('canvas02');
canvas2.width = 200;
canvas2.height = 200;
if (canvas2.getContext) {
  var context2 = canvas2.getContext('2d');
  // 新しいパスを開始する
  context2.beginPath();

  // 45度くらい傾ける
  context2.rotate(45 * Math.PI / 180); 

  // 四角の生成
  context2.rect(70, 50, 70, 70);

  // 塗りつぶし背景色の設定
  context2.fillStyle = '#ddd';

  // 塗りつぶし
  context2.fill();

  // 輪郭線の描画
  context2.stroke();

  // 新しいパスを開始する
  context2.beginPath();

  // 20度くらい傾ける
  context2.rotate(20 * Math.PI / 180); 

  // 四角の生成
  context2.rect(60, -100, 70, 70);

  // 塗りつぶし
  context2.fill();

  // 輪郭線の描画
  context2.stroke();
}

context.translate(x,y)

移動、X軸方向Y軸方向への移動を行って下さい。
指定パスからいくつ移動する?って指定を行います。

var canvas3 = document.getElementById('canvas03');
canvas3.width = 200;
canvas3.height = 200;
if (canvas3.getContext) {
  var context3 = canvas3.getContext('2d');
  // 新しいパスを開始する
  context3.beginPath();

  // 四角の生成
  context3.rect(70, 50, 70, 70);

  // 動かしますよ
  context3.translate(50,50); 

  // 四角の生成
  context3.rect(70, 50, 70, 70);

  // 動かしますよ
  context3.translate(-100,-100); 

  // 四角の生成
  context3.rect(70, 50, 70, 70);

  // 塗りつぶし背景色の設定
  context3.fillStyle = '#ddd';

  // 塗りつぶし
  context3.fill();

  // 輪郭線の描画
  context3.stroke();
}

context.transform(a,b,c,d,e,f)
context.setTransform(a,b,c,d,e,f)

いわゆるマトリクスでの指定です。

a:X軸への伸縮
b:Y軸への傾斜(回転)
c:X軸への傾斜(回転)
d:Y軸への伸縮
e:X軸への移動
f:Y軸への移動

一度に指定できるらしいんですけど・・・
scale(x, y)は、setTransform(x, 0, 0, y, 0, 0)と同じ
rotate(angle)は、setTransform(Math.cos(angle), Math.sin(angle), -Math.sin(angle), Math.cos(angle), 0, 0)と同じ
translate(x, y)は、setTransform(1, 0, 0, 1, x, y)と同じ
(๑´ڡ`๑)
基本指定は同じです。

違い

transform()
【現在の変換マトリックスと掛け合わせて変換マトリックスを適用する】

setTransform()
【現在の変換マトリックスをリセットしてから変換マトリックスを適用する】

つまり、色々な前回値を引き継いで指定するか0からとして指定しなおすかの違いです。

順番に気をつけろ!!!

なんや冒頭で順番が違うと形も違ってくるので気をつけてね。的な話を一瞬しました。
ではどうなの?なお話をやっていきます。
[拡大して回転して拡大] と [拡大して拡大して回転]で比較してみましょう。

拡大して回転して拡大

var canvas4 = document.getElementById('canvas04');
canvas4.width = 200;
canvas4.height = 200;
if (canvas4.getContext) {
  var context4 = canvas4.getContext('2d');
  // 新しいパスを開始する
  context4.beginPath();

  // 縦方向に2倍
  context4.scale(1,2); 

  // 90度くらい傾ける
  context4.rotate(90 * Math.PI / 180); 

  // 横方向に2倍
  context4.scale(2,1); 

  // 四角の生成
  context4.rect(10, -100, 30, 30);

  // 輪郭線の描画
  context4.stroke();
}

拡大して拡大して回転

var canvas5 = document.getElementById('canvas05');
canvas5.width = 200;
canvas5.height = 200;
if (canvas5.getContext) {
  var context5 = canvas5.getContext('2d');
  // 新しいパスを開始する
  context5.beginPath();

  // 縦方向に2倍
  context5.scale(1,2); 

  // 横方向に2倍
  context5.scale(2,1); 

  // 90度くらい傾ける
  context5.rotate(90 * Math.PI / 180); 

  // 四角の生成
  context5.rect(30, -60, 30, 30);

  // 輪郭線の描画
  context5.stroke();
}

なんで?

面白いですねぇ。
さらっと説明だけ入れておくと

  1. 縦方向に2倍伸ばすで
  2. 横向きにさせるわ!
  3. 横方向に2倍伸ばすで
  4. ・・・?長方形になってもうた

まず流れとしては上記になりますね。
で、問題は2と3部分。
回転させる事によって、縦部分が横になります。
処理はそのまま【横】を2倍してって命令してるわけなので、そのまま2倍します。
結果、同じ辺が2倍されるので、長方形になるんですね
※あくまでも90度横倒しにした時のお話

どんな風に推移していくのか見てみたいかも

わかりやすいように90度回転させたものと比較してみましたが
実際どんな感じで変わってしまうのか?
実験してみましょう。

var canvas6 = document.getElementById('canvas06'),
    intervalObj = "";
canvas6.width = 200;
canvas6.height = 200;
var context6 = canvas6.getContext('2d');

$('#canvas06Start').on('click',function()
{
  clearInterval(intervalObj);
  // canvas内リセット
  context6.clearRect(0, 0, 200, 200)

  var yCnt = 80;
      rectCnt = 1;
  intervalObj = setInterval(function()
  {
    // 新しいパスを開始する
    context6.beginPath();
    // canvas内リセット
    context6.clearRect(0, 0, 200, 200)
    // 色々な状態を保存
    context6.save()
    context6.scale(1,2); 
    context6.rotate(rectCnt * Math.PI / 180); 
    context6.scale(2,1); 
    context6.rect(20, yCnt, 30, 30);
    context6.stroke();
    // 設定を元に戻す
    context6.restore()
    rectCnt++;
    yCnt+= -2;
    if(rectCnt >= 90) {
      clearInterval(intervalObj);
      return false;
    }
  }, 30);
})

細かく調整なんかしてないのでアレですが
こんな感じで動いてるんですね。
徐々にのびーって行く感じ。ええ。まぁ、こんなんですいません。