HTML+JavaScriptだけでブラウザに図形描画(3) - Canvas API -

2012年10月11日(木)
山田 祥寛(YAMADA, Yoshihiro)

TIPS 030:画像を拡大/回転/変形して表示する

Canvas APIでは、scale(拡大縮小)、rotate(回転)、translate(移動)、transform(変形)など、図形を変形/加工するためのさまざまなメソッドが用意されています。以下では、これらのメソッドを利用した例を見てみましょう。

[リスト03]画像を拡大/回転/変形するコード(transform.html)

window.addEventListener('DOMContentLoaded',
  function() {
    if (HTMLCanvasElement) {
      var cv = document.querySelector('#cv');
      var c = cv.getContext('2d');
      // 初期状態のコンテキストをあらかじめ保存
      for (var i = 0; i < 3; i++) { c.save(); }
      // 画像を準備
      var img = new Image();
      img.src = 'wings.jpg';
      img.addEventListener('load', function(e) {
        // 半分に縮小して描画
        c.scale(0.5, 0.5);
        c.drawImage(img, 0, 0);
 
        // 30°回転したものを描画
        c.restore();
        c.rotate(30 * Math.PI / 180);
        c.drawImage(img, 50, 50);
 
        // (180, 200)ずらした上で描画
        c.restore();
        c.translate(180, 200);
        c.drawImage(img, 0, 0);
 
        // 変形マトリクスで変換した上で描画
        c.restore();
        c.transform(1, 1, 1, -1, 0, 0);
        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メソッドを使って、以下のように書いても良いでしょう。

  c.setTransform(1, 0, 0, 1, 0, 0);

TIPS 031:キャンバス上の図形の一部を切り出す/貼り付ける

getImageDataメソッドを利用すると、キャンバス上の特定の領域を切り出すことができます。また、切り出した画像はputImageDataメソッドを利用することで、同じキャンバス(または異なるキャンバス)に貼り付けることができます。

以下は、上のキャンバスに描画した画像の一部を切り出し、下のキャンバスに貼り付ける例です。

[リスト04]キャンバスに描画された図形の一部をコピーするコード(imageData.html)

window.addEventListener('DOMContentLoaded',
  function() {
    if (HTMLCanvasElement) {
      // 上下キャンバスのコンテキストを準備
      var cv = document.querySelector('#cv');
      var c = cv.getContext('2d');
      var cv2 = document.querySelector('#cv2');
      var c2 = cv2.getContext('2d');
      // 上のキャンバスに画像を貼り付け
      var img = new Image();
      img.src = 'rin.jpg';
      img.addEventListener('load', function(e) {
        c.drawImage(img, 0, 0, 400, 300);
        // 座標(180, 150)から150×150の大きさで画像を切り出し
        var d  = c.getImageData(180, 150, 150, 150);
        // 下のキャンバス(50, 50)の位置に切り出した画像を貼り付け
        c2.putImageData(d, 50, 50);
      });
    }
  }
);
...中略...
<canvas id="cv" width="400" height="300">
Canvas機能に対応したブラウザでアクセスしてください。
</canvas><br />
<canvas id="cv2" width="400" height="300">
Canvas機能に対応したブラウザでアクセスしてください。
</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つの要素で表現しているわけです。これらの値を操作することで、色味や透明度を変化させた上で、画像を貼り付けるということもできるでしょう。

  • Canvas APIを使ってブラウザに図形を描画するサンプル(3)

著者
山田 祥寛(YAMADA, Yoshihiro)
WINGSプロジェクト

有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表:山田祥寛)。おもな活動は、Web開発分野の書籍/雑誌/Web記事の執筆。ほかに海外記事の翻訳、講演なども幅広く手がける。2011年3月時点での登録メンバは36名で、現在もプロジェクトメンバーを募集中。

連載バックナンバー

Think ITメルマガ会員登録受付中

Think ITでは、技術情報が詰まったメールマガジン「Think IT Weekly」の配信サービスを提供しています。メルマガ会員登録を済ませれば、メルマガだけでなく、さまざまな限定特典を入手できるようになります。

Think ITメルマガ会員のサービス内容を見る

他にもこの記事が読まれています