Visit Mozilla.org

Canvas tutorial:Using images

出典: MDC

目次

canvas のより楽しい機能の一つは画像を使う能力です。これらはダイナミックな写真の合成やグラフの背景として使うこと等ができます。また現在それはテキストを追加する唯一の方法です(仕様はテキストを描画する機能を含んでいません)。外部画像は Gecko がサポートしている全てのフォーマット(例えば、PNG、 GIF や JPEG フォーマット)が利用できます。同じページの他の canvas 要素もソースとして使うことができます。

[編集] 画像のインポート

画像のインポートは基本的に2ステップの作業です:

  • 最初に、JavaScript の Image オブジェクトか他の canvas をソースとして参照する必要があります。ただ、 URL や パスを与えるだけで画像を使うことはできません。
  • 次に、drawImage 関数を使って canvas に画像を描きます。


最初にステップ1をみてみましょう。基本的に三つの選択肢が利用可能です。

[編集] 同じページの画像を使う

document.getElementsByTagName メソッド、もし画像に id 属性があるならばdocument.getElementById メソッドを使ってあるページの全ての画像にアクセスすることができます。

[編集] 他の canvas 要素を使う

普通の画像と同様に document.getElementsByTagName メソッドか document.getElementById メソッドを使って他の canvas 要素にアクセスできます。入力元の canvas を使う前に使おうとしている canvas に何かが描かれているか確認してください。

これのより実践的な利用方法の一つは2番目の canvas 要素を他の大きな canvas のサムネイルビューとして使うことです。

[編集] 一から画像を作る

最後の選択肢はスクリプトの中で新たな Image オブジェクト作ることです。このアプローチの主な短所は画像が読み込まれるのを待つ必要があるのでスクリプトが途中で停止しないために何らかの形の画像の先読みが必要ということです。

基本的に、新しい画像オブジェクトを作るにはこのようにします:

var img = new Image();   // 新しい Image オブジェクトを作る
img.src = 'myImage.png'; // ソースのパスを設定する

この画像が実行されたとき、画像は読み込みを始めます。もし drawImage 文が実行された時に読み込みが完了していない場合、画像が読み込み終わるまでスクリプトは停止します。もしあなたがこれの発生を防ぎたいなら、onload イベントハンドラを使ってください:

var img = new Image();   // 新しい Image オブジェクトを作る
img.onload = function(){
  // drawImage 文をここで実行
}
img.src = 'myImage.png'; // ソースのパスを設定する

あなたが1つの外部画像をしか使わないならこれは良い方法となりえますが、ひとたび1つ以上を追跡する必要があると、より賢い手段が必要になります。画像の先読み方法を見ることはこのチュートリアルの範囲を超えていますが、あなたは完全な解決策を JavaScript Image Preloader で調べることができます。

[編集] data: url スキームで画像を埋め込む

その他の画像を含めるための方法は、data: url を利用することです。データ URL は画像を、あなたのコード内に直接書かれた Base64 形式の文字列として完全に定義することができます。データ URL の長所の一つは、個別にサーバとのやり取りをしなくてもすぐに画像の表示ができることです。(その他の長所としては CSS, Javascript, HTML, 画像などを一つのファイルにカプセル化することによって、他の場所に移動しやすくなります。) いくつかの短所もあります。この方法では画像がキャッシュされず、また大きなサイズの画像はエンコードされた URL がとても長くなってしまいます:

var img_src = 'data:image/gif;base64,R0lGODlhCwALAIAAAAAA3pn/ZiH5BAEAAAEALAAAAAALAAsAAAIUhA+hkcuO4lmNVindo7qyrIXiGBYAOw==';

[編集] drawImage

ひとたび、ソース画像オブジェクトへの参照を持っていれば、それを canvas に描画するために drawImage メソッドを使うことがでます。後で見るように drawImage メソッドは詰め込み過ぎで3つの異なるヴァリエーションをもっています。そのなかでより単純なものはこのようになります。

drawImage(image, x, y)

Where image は画像か canvas オブジェクトへの参照is a reference to our image or canvas object. xy はターゲットの canvas の画像が置かれるべき座標を形づくります。

[編集] drawImage 例 1

以下の例で外部画像を小さな折れ線のグラフ背景として使っています。背景を使うと入念に背景を描く必要がないのでスクリプトがかなり小さくなる場合があります。ここでは1つの画像しか使っていないので、画像オブジェクトの onload イベントハンドラを描画の文を実行するために使っています。drawImage メソッドは背景を canvas の左上の角である座標 (0,0) に置きます。

この例を見る

  function draw() {
    var ctx = document.getElementById('canvas').getContext('2d');
    var img = new Image();
    img.onload = function(){
      ctx.drawImage(img,0,0);
      ctx.beginPath();
      ctx.moveTo(30,96);
      ctx.lineTo(70,66);
      ctx.lineTo(103,76);
      ctx.lineTo(170,15);
      ctx.stroke();
    }
    img.src = 'images/backdrop.png';
  }

[編集] 伸縮

drawImage メソッドの2番目のヴァリエーションは2つの新しいパラメタを追加し canvas に伸縮した画像を置くことができます。

drawImage(image, x, y, width, height)

widthheight はターゲット canvas での画像の大きさです。

[編集] drawImage 例 2

この例では画像を背景として使い、それを canvas 上で何回か繰り返します。これは単にループで異なった位置に伸縮された画像を置いています。下のコードの最初の for ループは行を通り、次の for ループは列です。画像はオリジナルサイズの 50x38 ピクセルの 1/3 に伸縮されています。このチュートリアルの後半でこれがカスタムパターンを作成することによってもどう実現されるかを見るでしょう。

注意: 画像は拡大するとぼやけたり、とても縮小すると粗くなりえます。もし、読みやすいままで残る必要がある何らかのテキストがあるなら、伸縮はおそらく最適には行われません。

この例を見る

ソース画像
ソース画像
  function draw() {
    var ctx = document.getElementById('canvas').getContext('2d');
    var img = new Image();
    img.onload = function(){
      for (i=0;i<4;i++){
        for (j=0;j<3;j++){
          ctx.drawImage(img,j*50,i*38,50,38);
        }
      }
    }
    img.src = 'images/rhino.jpg';
  }

[編集] スライス

三番目の、そして最後の、drawImage メソッドのヴァリエーションは 8 つの新しいパラメタを持ちます。このメソッドをソース画像の一部をスライスし、それらを canvas 上に描きます。

drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)

最初の image パラメタは、他のヴァリエーションと同じで画像オブジェクトか他の canvas 要素への参照のどちらかです。他の 8 つのパラメタためには右の画像をみるのが一番です。最初の 4 つのパラメタはソース画像の場所と大きさを定義しています。最後の 4 つのパラメタはターゲットの canvas の位置と大きさを定義しています。

あなたが合成をしたいとき、スライスは便利な手段であるかもしれません。 あなたは、1つの画像ファイルの中にすべての要素を用意して、完全な図形を合成するこのメソッドを使うことができるもしれません。 例えば、あなたがチャートを作りたいなら、一列にすべての必要なテキストを含む PNG 画像を用意し、あなたのデータによっては非常に多くの困難なくチャートのスケールを変えられるかもしれません。 別の利点はあなたが個別にあらゆるイメージをロードする必要はないということです。別の利点は個々に全ての画像を読み込む必要がないということです。

[編集] drawImage 例 3

この例で、私は上で見たのと同じ際を使っていますが、今はその上部を切り取り、額縁の中に合成しています。額縁の画像は 24 ビット PNG 画像で保存されたドロップシャドウを含んでいてます。GIF と 8 ビット PNG 画像とは異なり、24 ビット PNG 画像はフル 8 ビットアルファチャンネルを含んでいるので、私はどんな背景の上にも置くことができ、マットの色を心配する必要はありません。

私は画像を読み込むために上の例とは異なる方法を採っています。HTML 文書に直接画像を置き、CSS ルール (display:none) でビューから隠しています。より簡単に選択できるように画像に id 属性を割り当てています。 スクリプト自体はとても単純です。私は最初に切りぬかれ、伸縮された画像を canvas 上に描き(最初の drawImage 文)、フレームを上に置いています(2番目の drawImage 文)。

この例を見る

ソース画像
ソース画像
function draw() {
  var canvas = document.getElementById('canvas');
  var ctx = canvas.getContext('2d');

  // 切りぬきを描く
  ctx.drawImage(document.getElementById('source'),
                33,71,104,124,21,20,87,104);

  // 枠を描く
  ctx.drawImage(document.getElementById('frame'),0,0);
}

[編集] アートギャラリの例

本章の最後の例では、私は小さいアートギャラリを作りました。 ギャラリはいくつかの画像を含むテーブルから成ります。 ページが読み込まれた時、ページの各画像に対して、canvas 要素が挿入され、枠がその周りには描かれます。

私の場合ではすべての画像が固定の幅と高さを持っており、その周りに描かれたフレームもそうです。あなたはスクリプトを画像の幅と高さを使用することで周りの枠が完全に合うように改良することができるでしょう。

下のコードは一目瞭然です。画像の配列をループし、新しい canvas 要素を順に追加しています。たぶん DOM にそれほどで明るくない人たちのために注意する唯一のことは、insertBefore メッソドの利用です。insertBefore は新しいノード(canvas 要素)を挿入したいと思う要素(画像)の親ノード(テーブルのセル)のメソッドです。

この例を見る

function draw() {

  // Loop through all images
  for (i=0;i<document.images.length;i++){

    // Don't add a canvas for the frame image
    if (document.images[i].getAttribute('id')!='frame'){

      // Create canvas element
      canvas = document.createElement('CANVAS');
      canvas.setAttribute('width',132);
      canvas.setAttribute('height',150);

      // Insert before the image
      document.images[i].parentNode.insertBefore(canvas,document.images[i]);

      ctx = canvas.getContext('2d');

      // Draw image to canvas
      ctx.drawImage(document.images[i],15,20);

      // Add frame
      ctx.drawImage(document.getElementById('frame'),0,0);
    }
  }
}

« »