HTML / Element

canvas要素の使い方

HTMLのcanvas要素は、Webページの中に「JavaScriptで絵を描ける四角い画面」を作ります。グラフ、ゲームの画面、画像の加工など、プログラムで絵を作ったり変えたりしたいときに使います。

先に結論

canvasにwidthとheightを指定し、JavaScriptから描画用のcontextを取得して絵を描きます。

その絵だけに情報を任せず、内容の説明やデータを普通のHTMLでも読めるようにします。すでに画像ファイルがあるだけなら、たいていはimgのほうが簡単です。

最小例

<canvas id="chart" width="320" height="180">
  グラフの内容: 1月12、2月18、3月14。
</canvas>
<p>グラフの値は、1月12、2月18、3月14です。</p>

<script>
  const canvas = document.querySelector("#chart");
  const context = canvas?.getContext("2d");

  if (context) {
    context.fillStyle = "#4c78c2";
    context.fillRect(24, 24, 80, 60);
  }
</script>

getContext("2d")は、2Dの図形や文字を描くための道具を返します。contextを取得できない場合に備えて、例では返り値があるときだけ描画しています。

青い円と緑の山を描く例です。

このページの例ではcanvasの中に青い円と緑の山を描いています。グラフの数値のような大切な情報は、この文のようにcanvasの外にも書きます。

widthとheightが決めるもの

canvasのwidthとheightは、canvasの中に保存する絵の大きさを決めます。省略したときは横300、高さ150です。

<canvas width="320" height="180"></canvas>

<style>
  canvas { width: 640px; height: 360px; }
</style>

この例は320×180の絵を、ページ上では640×360に拡大して表示します。HTML属性が決める絵の大きさと、CSSが決める画面上の大きさは別々です。比率が合わない値にすると、絵が伸びて見えることがあります。

JavaScriptでcanvas.widthやcanvas.heightを設定し直すと、描いた絵が消えて描画状態も初期化されます。同じ数値をもう一度入れた場合もリセットされるので、サイズ調整のつもりで何度も設定し直さないようにします。

描画用のcontextを選ぶ

getContext("2d")は2Dの描画用です。WebGLなど別のcontextもありますが、同じcanvasで一度使い始めたcontextの種類を、あとから別の種類へ切り替えることはできません。必要な種類を決めてから取得します。

  • グラフや簡単な図形を描く: 2d
  • 3Dグラフィックスを描く: WebGL系のcontext
  • contextを取得できない場合: getContext()の結果がnullになることがある

最初の一歩では、既存の画像を画面に置くだけなのか、JavaScriptで描画や加工を行いたいのかを考えましょう。

説明と操作方法も用意する

canvasの子どもとして書いた文章は、スクリプトが使えない場合などに表示するfallback contentです。canvasに絵が描かれているとき、その文章が絵の上にいつも重ねて表示されるわけではありません。そのため、図の説明やグラフの値など大切な内容は、canvasの外にもHTMLで用意します。

canvasの中のボタンのように、絵の一部を操作させる場合は、キーボードでも操作できる方法が必要です。見た目の操作領域と、fallbackに用意するfocus可能な操作箇所を対応させる考え方が仕様にあります。複雑なアプリでは、通常のHTMLのボタンや入力欄を使う方法も検討します。

別のサイトの画像を描くとき

別のサイトから読み込んだ画像をcanvasへ描けても、その画像のピクセルを読み出したり、canvasを画像ファイルとして保存したりできるとは限りません。読み込み元のサーバーがCORSによる許可を返さないと、ブラウザーがピクセルの読み出しや書き出しを止めることがあります。

これは、あるサイトのページが別のサイトの画像データを勝手に読み取らないための安全機能です。画像を表示できることと、画像データを読み出せることは別です。

よくある間違い

  • canvasの幅をCSSだけで変え、描画する領域の大きさも変わったと思う。
  • widthやheightを書き換えた後も、前に描いた絵やcontextの設定が残ると思う。
  • 絵に含まれる大切な説明をcanvasのピクセルだけに入れ、テキストでも説明しない。
  • 別サイトの画像を描画できたので、そのピクセルも必ず読み出せると思う。
  • 静止画を一枚見せるだけなのに、必要のないJavaScript描画を作る。

Atlasで詳しく確認する

bitmap寸法とCSS表示寸法の違い、context mode、サイズ変更時のリセット、fallback descendants、origin-cleanと実装Evidenceの範囲は、Yugien Atlasのcanvas要素ページで確認できます。画像の代替テキストはimg、画面に合わせて画像候補を切り替える方法はpictureも参照してください。