JavaScript:端末の短辺に合わせた正方形キャンバスを設定する

JavaScript

どの端末でも同じような縮尺でキャンバスに描いた図形や文字を表示したいと考えました。
キャンバスサイズを端末の短辺(短い方のサイズ)に合わせて正方形とし、端末のサイズが途中で変更した際にも対応するようにしました。

スマホなら傾けて縦横の幅を変えたり、パソコンのブラウザならウインドウサイズを変更したりして確認してみてください。どのサイズでも同じ縮尺で表示されるはずです。

実行イメージ

縦長端末の場合(下に余白ができます)

横長端末の場合(右に余白ができます)

ソースコード

index.html

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<meta name="viewport" content="width=device-width,user-scalable=yes">
		<script src="main.js" type="text/javascript"></script>
		<title>端末の短辺に合わせた正方形キャンバスを設定する</title>
		<style>
			*{
				margin: 0;
				padding: 0;
			}
			#canvas{
				display: block;
			}
			html, body, #wrapper{
				width: 100%;
				height: 100%;
			}
		</style>
	</head>
	<body>
		<div id="wrapper">
			<canvas id="canvas" width="" height=""></canvas>
		</div>
	</body>
</html>

HTML補足

canvasタグをdivタグで囲って、CSSで以下の設定することにより端末サイズにキャンバスサイズをフィットさせています。

#canvas{
	display: block;
}
html, body, #wrapper{
	width: 100%;
	height: 100%;
}

main.js

/* ---------------------------------------------------------------------
	端末の短辺に合わせた正方形キャンバスを設定する
 --------------------------------------------------------------------- */
/*
 * グローバル変数
 */
let wrapper = null;				// キャンバスの親要素
let canvas = null;				// キャンバス
let g = null;					// コンテキスト
let game_size;					// サイズ
let scale;						// スケール
let $id = function(id){ return document.getElementById(id); };	// DOM取得用

/*
 * 定数
 */
const BACKGROUND_COLOR = "black";		// 背景色
const ARC_COLOR = "yellowgreen";		// 円の色
const TEXT_COLOR = "white";				// 文字色

/*
 * 端末サイズに応じてキャンバスのサイズを変更する
 */
function getSize(){
	// 短辺をキャンバスの短辺とする
	game_size = wrapper.offsetWidth >= wrapper.offsetHeight ? wrapper.offsetHeight : wrapper.offsetWidth;
	console.log("キャンバスの短辺: " + game_size + "px");
	// キャンバスのサイズを再設定(短辺に合わせて正方形とする)
	canvas.width = canvas.height = game_size;
	// 縮尺を設定(キャンバス短辺=320px のとき 縮尺=1 とする)
	scale = game_size / 320.0;
	g.scale(scale, scale);
}

/*
 * リサイズ時(キャンバスサイズを再設定し描画)
 */
window.addEventListener("resize", function(){
	getSize();
	draw();
});

/*
 * 描画する(320x320ピクセルの画面を基本として描画している)
 */
function draw(){
	// 背景色を描画
	g.fillStyle = BACKGROUND_COLOR;
	g.fillRect(0, 0, canvas.width, canvas.height);

	// 塗りつぶし円を描画
	g.fillStyle = ARC_COLOR;
	g.beginPath();
	g.arc(160, 160, 80, 0, Math.PI*2, true);
	g.fill();

	// 文字列を描画
	g.globalAlpha = 0.6;	// 透明度
	g.fillStyle = TEXT_COLOR;
	g.font = "bold 18px serif";	// 太字 18ピクセル 明朝体
	g.textBaseline = "top";
	g.fillText("No man is a failure who has friends.", 12, 151);
}

/*
 * 起動時の処理
 */
window.addEventListener("load", function(){
	// キャンバスの親要素情報取得(親要素が無いとキャンバスのサイズが画面いっぱいに表示できないため)
	wrapper = $id("wrapper");

	// キャンバス情報取得
	canvas = $id("canvas");
	g = canvas.getContext("2d");

	// 端末サイズを再設定
	getSize();

	// 描画
	draw();
});

仮想の端末サイズは320×320ピクセル

このプログラムでは、異なる端末サイズでもプログラム上でキャンバス描画関数のxy座標を修正することなく描画できるようにしています。

そのため仮想の端末サイズというものを設定しています。
プログラム上は、320×320ピクセルを仮想キャンバスサイズとして、端末サイズが切り替わるたびに呼び出されるようにしています。

ポイントとなるのは、関数getSizeです。

function getSize(){
	// 短辺をキャンバスの短辺とする
	game_size = wrapper.offsetWidth >= wrapper.offsetHeight ? wrapper.offsetHeight : wrapper.offsetWidth;
	console.log("キャンバスの短辺: " + game_size + "px");
	// キャンバスのサイズを再設定(短辺に合わせて正方形とする)
	canvas.width = canvas.height = game_size;
	// 縮尺を設定(キャンバス短辺=320px のとき 縮尺=1 とする)
	scale = game_size / 320.0;
	g.scale(scale, scale);
}

もし仮想端末サイズを500×500ピクセルにしたい場合は、

scale = game_size / 500.0;

のようにすればOKです。

注意点

このプログラムだと端末サイズが320を下回る場合は、上手く描画できなくなります。(今時320ピクセルを下回る端末はないため問題はないと思いますが…)

例)端末の短辺サイズが320ピクセルを下回る場合

端末短辺サイズが320ピクセルを下回ると表示がずれる

以上、JavaScript:端末の短辺に合わせた正方形キャンバスを設定するでした。

コメント

タイトルとURLをコピーしました