canvas を画面サイズに合わせる方法

キャンバス要素を画面全体に表示します。

結論

sample-fit-canvas-screen-size.html<!DOCTYPE html>
<html>
  <head>
    <meta name="viewport" content="width=device-width,initial-scale=1"/>
    <style>
html, body, #canvas {
  display: block;
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
}
    </style>
  </head>
  <body>
    <canvas id="canvas"></canvas>
    <script>
const onRepaint = function() {
  console.log('repaint');

  const canvas =  document.getElementById('canvas');
  const context = canvas.getContext('2d');
  context.fillStyle = 'red';
  context.fillRect(0, 0, canvas.width, canvas.height);
  context.fillStyle = 'blue';
  context.fillRect(10, 10, canvas.width-20, canvas.height-20);
};
const onResize = function() {
  console.log('resize');

  const canvas =  document.getElementById('canvas');
  console.log(canvas.height, canvas.clientHeight, window.innerHeight);

  canvas.width = canvas.clientWidth;
  canvas.height = canvas.clientHeight;

  onRepaint();
};
window.addEventListener('DOMContentLoaded', onResize);
window.addEventListener('resize', onResize);
    </script>
  </body>
</html>

サンプルページ

スマホ用にビューポートを設定する

<meta name="viewport" content="width=device-width,initial-scale=1"/>

スマホ環境でビューポートを端末サイズに合わせます。

要素を画面サイズに合わせる

html, body, #canvas {
  display: block;
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
}

要素(<canvas id="canvas">)を画面サイズに合わせます。
具体的には、次の5点を変更します。

  • <html>を画面サイズまで拡張する
    • height: 100%;で高さを拡張する
  • <body>の余白を削除する
    • margin: 0;で不要な余白を削除する
  • <body><html>まで拡張する
    • height: 100%;で高さを拡張する
  • <canvas><body>まで拡張する
    • width: 100%;で横幅を拡張する
    • height: 100%;で高さを拡張する
  • <canvas>をブロック要素として表示する
    • display: block;でブロック要素として表示する
      • <canvas> の初期設定はインライン要素です

備考(100vh を使う)

body {
  height: 100vh;
  margin: 0;
}
#canvas {
  display: block;
  width: 100%;
  height: 100%;
}

body { height: 100vh } を設定する方法もあります。ただし、100%100vhには、違いがあります。

100vh の最大の問題は、スマホ環境のアドレスバーがある場合、アドレスバー分の領域がはみ出すことです。100vhは画面の高さであるため、アドレスバーの領域も含めて計算されるからです。100vhは画面のコンテンツ表示領域ではありません。画面のビューポートの高さなのです。他にもスマホ環境のキーボード周りの問題もあります。

別解(キャンバスを浮かせる)

#canvas {
  display: block;
  position: fixed;
  top: 0;
  left: 0;
  z-index: 999;
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
/*opacity: 0.5;*/
}

<canvas id="canvas"> を他要素の前面に配置して、画面サイズまで拡張します。

「ページに別要素を表示している状態で、一時的にキャンバスでページを覆い尽くす」などの用途に利用できます。

<canvas>の表示サイズとキャンバスサイズを一致させる

<canvas>には、2つのサイズがあります。「HTML要素として表示サイズ」と「キャンバスのサイズ」です。具体的には、要素の clientWidth / clientHeight (表示サイズ)と width / height (キャンバスサイズ)です。

表示サイズとキャンバスサイズは、常に一致しているわけではありません。表示サイズは、CSS的な要素サイズの変更によって常に変化します。キャンバスサイズは、明示的なサイズ指定を行うことで変更することができます。表示サイズとキャンバスサイズが異なる場合、ボヤケたような不自然な表示になります。

const canvas =  document.getElementById('canvas');
canvas.width = canvas.clientWidth;
canvas.height = canvas.clientHeight;

備考(window.innerHeight を使う)

const canvas =  document.getElementById('canvas');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;

window.innerHeight (ウィンドウの高さ)を使用します。ただし、次の問題があります。

<canvas> のキャンバスサイズにwindow.innerHeight (ウィンドウの高さ)を指定しても、<canvas>の表示サイズがウィンドウの高さと異なる場合、表示サイズとキャンバスサイズの不一致により表示の歪みが発生します。キャンバスサイズをウィンドウの高さに設定しても、<canvas>の表示サイズが連動して変更されるわけではない点を考慮してください。

ブラウザのサイズ変更を監視する

window.addEventListener('resize', onResize);

ブラウザのサイズ変更を考慮して、resize イベントを監視し、表示サイズの変更をキャンバスサイズに随時再設定します。

まとめ

  1. ビューポートを適切に設定する
  2. 要素の表示サイズを画面サイズに合わせる
  3. キャンバスサイズを表示サイズに設定する
  4. 表示サイズの変更をキャンバスサイズに適時再設定する