ITエンジニア勉強ブログ

自分が学んだことを共有していきます。

canvasのサイズとBootstrap

この記事では、HTMLのcanvasタグのサイズ設定と、それを更にBootstrapと組み合わせてレスポンシブデザインにする方法を説明します。


See the Pen
Untitled
by Imai (@imai1)
on CodePen.

発端:JavaScriptでちょっとローグライクゲームでも作ってみようかなと思ったのですが、マップのアスペクト比を維持しつつ様々なスクリーンサイズに対応したり、メッセージウィンドウをレスポンシブに改行したりするにはどうしたら良いのかと考えたことがきっかけです。

canvasのサイズとスタイルのサイズ

canvasタグには二種類のサイズ設定があります。canvasタグの属性width heightと、タグのstyle属性のwidth heightです。

<canvas width="300px" height="150px" style="width: 500px; height: 250px;">
  • タグのwidthおよびheight属性は、描画領域の座標空間のサイズを設定するためのものです。
  • 一方、style属性のwidthおよびheightは、canvasタグがブラウザ上で描画される際のサイズを指定するためのものです。
  • ただし、style属性の設定がない場合は、タグのwidthおよびheight属性が後者にも適用されます。

具体的な例で見てみましょう。

まず、canvas内に、固定の大きさの矩形と、canvasのサイズを描画する次の関数を用意しました。

function drawSample(canvas) {
  const context = canvas.getContext("2d");
  context.fillStyle = "white";
  context.fillText(`canvas.width=${canvas.width}, canvas.height=${canvas.height}`, 20, 20);
  context.fillRect(20, 30, 100, 100);
}

それを次のタグに適用します。

<canvas id="canvas1" class="bg-dark" width="300px" height="150px" style="width: 500px; height: 250px;"></canvas>
<canvas id="canvas2" class="bg-dark" width="300px" height="150px"></canvas>
<canvas id="canvas3" class="bg-dark" width="500px" height="250px"></canvas>
drawSample(document.getElementById("canvas1"));
drawSample(document.getElementById("canvas2"));
drawSample(document.getElementById("canvas3"));

すると、レンダリング結果は次のようになります。


ID 描画領域の論理サイズ ブラウザ上の表示サイズ
canvas1 300 x 150 500 x 250
canvas2 300 x 150 300 x 150
canvas3 500 x 250 500 x 250

Bootstrapにcanvasを設置

ここまでの説明を踏まえて、Bootstrapにおいて、固定のアスペクト比canvasをグリッド内に配置する例は以下のようになります。

<div class="row">
  <div class="col-sm-8 border">
    <canvas id="canvas4" class="bg-dark ratio ratio-1x1" width="600px" height="600px"></canvas>
  </div>
  <div class="col-sm-4 border">
    <p>Message Window</p>
  </div>
</div>
  • row colでグリッドを作成します。これによってcanvasの横幅は(別のスタイルで上書きしなければ)自動的に定まります。
  • ratio ratio-1x1を設定することで、アスペクト比を設定します。比率はこの他にratio-4x3 ratio-16x9 ratio-21x9が用意されています。
  • canvasタグのwidth heightで描画領域の論理サイズを設定します。

レンダリング結果は次のようになります。

ブラウザの横幅を変えたり、CodePenの縮尺を変更したりしても、canvasアスペクト比と論理サイズは変わらないまま、ブラウザ上の表示サイズのみが変わることを確認してみてください。Message Window(ローグライクゲームを想定)は、ブラウザの幅を狭めると縦置きになります。

なお、表示サイズに対してcanvasタグのwidth heightが小さすぎると、画像の拡大処理が適用されてぼやけた表示になります。


グリッドに関する説明は本記事では省略しますが、詳しく知りたい方は以下もご覧いただけたら嬉しいです。

imai1.hatenablog.com