TIPS 030:画像を拡大/回転/変形して表示する
Canvas APIでは、scale(拡大縮小)、rotate(回転)、translate(移動)、transform(変形)など、図形を変形/加工するためのさまざまなメソッドが用意されています。以下では、これらのメソッドを利用した例を見てみましょう。
[リスト03]画像を拡大/回転/変形するコード(transform.html)
01 | window.addEventListener('DOMContentLoaded', |
03 | if (HTMLCanvasElement) { |
04 | var cv = document.querySelector('#cv'); |
05 | var c = cv.getContext('2d'); |
06 | // 初期状態のコンテキストをあらかじめ保存 |
07 | for (var i = 0; i < 3; i++) { c.save(); } |
09 | var img = new Image(); |
10 | img.src = 'wings.jpg'; |
11 | img.addEventListener('load', function(e) { |
14 | c.drawImage(img, 0, 0); |
18 | c.rotate(30 * Math.PI / 180); |
19 | c.drawImage(img, 50, 50); |
23 | c.translate(180, 200); |
24 | c.drawImage(img, 0, 0); |
28 | c.transform(1, 1, 1, -1, 0, 0); |
29 | c.drawImage(img, 70, 100); |
図3:画像を加工した上で貼り付け(クリックで拡大)
それぞれの構文を見てみましょう。
[構文]scale/rotate/translate/transformメソッド
- scale(横倍率, 縦倍率) … 拡大/縮小
- rotate(角度) … 回転
- translate(水平方向, 垂直方向) … 移動
- transform(m11, m12, m21, m22, dx, dy) … 変形
transformメソッドは、scale/rotate/translateメソッドをひとつにまとめたメソッドと言っても良いでしょう。以下のような変換マトリクスを使って、図形を変形させます。
図4:図形を変形させる変換マトリクス(クリックで拡大)
単純な拡大/縮小、回転、移動には専用のメソッドの方が簡単ですが、より複雑な座標変換には、transformメソッドを利用します。以下に簡単な利用パターンをまとめます。
表2:transformメソッドの利用例
例 |
概要 |
transform(x, 0, 0, y, 0, 0) |
横x倍、縦y倍に拡大 |
transform(Math.cos(r), Math.sin(r), -Math.sin(r), Math.cos(r), 0, 0) |
r(ラジアン)だけ回転 |
transform(1, 0, 0, 1, x, y) |
水平方向にx、垂直方向にyだけ移動 |
なお、transformメソッドは、実行都度に変換マトリクスを累積していきます。
もしも新たに変換マトリクスを適用したい(または、状態を初期化したい)という場合には、setTransformメソッドを利用してください。setTransformメソッドは、変換マトリクスを累積するのではなく、新たに設定し直します。
サンプルでは、キャンバス状態の初期化にrestoreメソッドを利用していますが、代わりにsetTransformメソッドを使って、以下のように書いても良いでしょう。
1 | c.setTransform(1, 0, 0, 1, 0, 0); |
TIPS 031:キャンバス上の図形の一部を切り出す/貼り付ける
getImageDataメソッドを利用すると、キャンバス上の特定の領域を切り出すことができます。また、切り出した画像はputImageDataメソッドを利用することで、同じキャンバス(または異なるキャンバス)に貼り付けることができます。
以下は、上のキャンバスに描画した画像の一部を切り出し、下のキャンバスに貼り付ける例です。
[リスト04]キャンバスに描画された図形の一部をコピーするコード(imageData.html)
01 | window.addEventListener('DOMContentLoaded', |
03 | if (HTMLCanvasElement) { |
05 | var cv = document.querySelector('#cv'); |
06 | var c = cv.getContext('2d'); |
07 | var cv2 = document.querySelector('#cv2'); |
08 | var c2 = cv2.getContext('2d'); |
10 | var img = new Image(); |
12 | img.addEventListener('load', function(e) { |
13 | c.drawImage(img, 0, 0, 400, 300); |
14 | // 座標(180, 150)から150×150の大きさで画像を切り出し |
15 | var d = c.getImageData(180, 150, 150, 150); |
16 | // 下のキャンバス(50, 50)の位置に切り出した画像を貼り付け |
17 | c2.putImageData(d, 50, 50); |
23 | <canvas id="cv" width="400" height="300"> |
24 | Canvas機能に対応したブラウザでアクセスしてください。 |
26 | <canvas id="cv2" width="400" height="300"> |
27 | Canvas機能に対応したブラウザでアクセスしてください。 |
図5:上キャンバスの一部を下キャンバスにコピー(クリックで拡大)
getImageDataメソッドの構文は、以下のとおりです。
[構文]getImageDataメソッド
- getImageData(x, y, width, height)
これで座標(x, y)を基点としてwidth×heightのサイズで画像データを取得しなさいという意味になります。getImageDataメソッドの戻り値は、ImageDataオブジェクトです。
ImageDataオブジェクトは、そのままputImageDataメソッドに渡せます。
[構文]putImageDataメソッド
- putImageData(ImageDataオブジェクト, x, y)
指定されたImageDataオブジェクトを、座標(x, y)に貼り付けます。
サンプルでは、ImageDataオブジェクトをそのまま貼り付けているだけですが、ImageDataオブジェクトはピクセルデータを配列として保持しています。
図6:画像の色味や透明度を変化させて貼り付けることができる(クリックで拡大)
ひとつのピクセルを赤、緑、青、不透明度という4つの要素で表現しているわけです。これらの値を操作することで、色味や透明度を変化させた上で、画像を貼り付けるということもできるでしょう。