Nekonote

Nekonote(ねこのて)もかりたい

【HTML/JavaScript】よくある canvas要素 に画像を表示する対応 【テンプレート付】

このエントリーをはてなブックマークに追加

おつかれさまです。

記事の前に、まずは にゃんこ成分 を充電します ( ˙꒳​˙ )

f:id:herrscherinnen:20190426001013j:plain

いい寝顔で疲れが癒されるぅ(๑˃̵ᴗ˂̵๑)


前回の記事はこちら

h-s-hige.hateblo.jp


canvasでは、画像やアニメーションが魅力的です。

○や□といった図形や、文字もかけますが、 ぱっと見栄えがよくなりそうなことをやるほうが楽しいです (。・-・。)

そこで今回は、canvas に画像を描画します。


canvas に画像を表示するには、大まかに次の手順が必要です。

  • Image オブジェクトを作る
  • Image オブジェクトに onload で実行されるイベントハンドラ を登録する
  • Image オブジェクトに src プロパティ を設定する

onload に登録する処理は、画像を描画する処理です。
src プロパティを設定すると、画像の読み込みが始まります。

そのため、srcプロパティよりも先に、onloadの登録が必要です。
逆にすると、onload が呼ばれないことがあります。

ソースコードはこちらが、参考になりました。

developer.mozilla.org

わかりやすいですが、すぐに壁にあたります。

画像が複数のときはどうすればいいのか…↷( ó╻ò)


やること

複数の画像を canvas に描画する。
canvas への描画は、すべての画像を読み込んだあとに行う。


やったこと

ロードを待ち合わせて描画するロジック。

  // 画像のパス一覧
  // https://picsum.photos/
  var sources = [
    "https://picsum.photos/240/360",
    "https://picsum.photos/240/320",
    "https://picsum.photos/240/280",
    "https://picsum.photos/240/240",
  ];

  // 画像のロードを待つ
  var waiting_for_load = sources.length;
  var images = Array.apply(null, Array(sources.length)).map(() => new Image());
  images.map((image, i) => {
    image.onload = () => --waiting_for_load == 0 && draw(); // 画像のロードが終わったら draw を呼んで描画します
    image.onerror = () => console.log("failed to load.");
    image.src = sources[i];
  });

  context.textBaseline = 'middle';

  var draw = () => {
    // キャンバスに画像を描画する
    // http://www.html5.jp/canvas/ref/method/drawImage.html
    images.forEach((image, i) => context.drawImage(image, image.width * i, canvas.height / 2 - image.height / 2));
  };

前回のソースに組み込みます。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>Title</title>
<style>
html, body {
  height: 100%;
  margin: 0;
}

#canvas {
  position: relative;
  left: 50%;
  top: 50%;
  margin-left: -480px; // canvas の width/2
  margin-top: -360px; // canvas の height/2
}
</style>
<script>
document.addEventListener('DOMContentLoaded', function () {
  var canvas = document.getElementById('canvas');
  var styles = canvas.getAttribute('style') || '';
  var context = canvas.getContext('2d');

  // canvasが見えるように、色を付けます
  context.fillStyle = 'rgba(0,0,16, 0.66)';
  context.fillRect(0, 0, canvas.width, canvas.height);

  var onResize = canvas => {
    var scale = Math.min(window.innerWidth / canvas.width, window.innerHeight / canvas.height);
    var transform = 'scale(' + scale + ',' + scale + ');';

    canvas.setAttribute('style', styles + 
      '    -moz-transform: ' + transform + 
      '     -ms-transform: ' + transform + 
      '      -o-transform: ' + transform + 
      '         transform: ' + transform + 
      ' -webkit-transform-origin: center center;' +
      '    -moz-transform-origin: center center;' +
      '     -ms-transform-origin: center center;' +
      '      -o-transform-origin: center center;' +
      '         transform-origin: center center;'
    );
  }

  onResize(canvas);
  window.addEventListener('resize', () => onResize(canvas), false);


  // 画像のパス一覧
  // https://picsum.photos/
  var sources = [
    "https://picsum.photos/240/360",
    "https://picsum.photos/240/320",
    "https://picsum.photos/240/280",
    "https://picsum.photos/240/240",
  ];

  // 画像のロードを待つ
  var waiting_for_load = sources.length;
  var images = Array.apply(null, Array(sources.length)).map(() => new Image());
  images.map((image, i) => {
    image.onload = () => --waiting_for_load == 0 && draw(); // 画像のロードが終わったら draw を呼んで描画します
    image.onerror = () => console.log("failed to load.");
    image.src = sources[i];
  });

  context.textBaseline = 'middle';

  var draw = () => {
    // キャンバスに画像を描画する
    // http://www.html5.jp/canvas/ref/method/drawImage.html
    images.forEach((image, i) => context.drawImage(image, image.width * i, canvas.height / 2 - image.height / 2));
  };
});

</script>
</head>
<body>
  <canvas id="canvas" width=960 height=720 style="position: relative; left: 50%; margin-left: -480px; top: 50%; margin-top: -360px;">
  </canvas>
</body>
</html>

これで canvas を急に使うことになっても、ざっくり安心 ( ˙꒳​˙ )

1file で動かせるのでお手軽です。


今回使ったダミー画像はこちら。

picsum.photos

画像を表示する drawimage メソッドはこちら。

www.html5.jp


今日もありがとうございました ٩(ˊᗜˋ*)و

おすすめ 記事