Skip to content

Instantly share code, notes, and snippets.

@mrgarita
Created March 4, 2024 02:48
Show Gist options
  • Save mrgarita/97822c9b1b05e40f4e268f054c43d54e to your computer and use it in GitHub Desktop.
Save mrgarita/97822c9b1b05e40f4e268f054c43d54e to your computer and use it in GitHub Desktop.
JS:スマホの縦でも横でもキャンバスが収まるようにする
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- Google Fonts -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@500&display=swap" rel="stylesheet">
<!-- /Google Fonts -->
<title>スマホの縦でも横でもキャンバスが収まるようにする</title>
<style>
*{
margin: 0;
padding: 0;
line-height: 0; /* ブラウザでキャンバスの下に隙間ができるのを防ぐ */
}
</style>
<script src="main.js" type="text/javascript"></script>
</head>
<body>
<canvas id="canvas" width="320" height="400"></canvas>
</body>
</html>
/*
* スマホの縦でも横でもキャンバスが収まるようにする
*/
let canvas = null; // キャンバス(描画領域)
let g = null; // 描画対象
let pos = {x:0, y:0}; // キャンバス上のXY座標
let canvasHeightRatio; // キャンバス幅に対する高さの割合
let resolutionRatio = 0; // 元キャンバスに対する表示サイズの大きさ割合
// 画像オブジェクト(画像ファイルをキャンバスで利用するため)
let img;
/*
* タッチして指を動かしている時の処理
*/
const touchMoveListener = (e) => {
// 端末のデフォルト動作をキャンセル
e.preventDefault();
// タッチ開始情報を取得
const touches = e.touches;
// ページ上のオフセット位置取得
const rect = e.target.getBoundingClientRect();
// キャンバス上のXY座標を取得
pos.x = Math.floor(touches[0].pageX/resolutionRatio - rect.left);
pos.y = Math.floor(touches[0].pageY/resolutionRatio - rect.top);
};
/*
* キャンバスに描画する
*/
const drawCanvas = () =>{
// 背景塗りつぶし
g.fillStyle = "royalblue";
g.fillRect(0, 0, canvas.width, canvas.height);
// テキスト描画
g.fillStyle = "snow";
const titleText = "Crime and Punishment";
const textObj = g.measureText(titleText); // キャンバス文字列の情報を得る
g.fillText(titleText, canvas.width/2-textObj.width/2, canvas.height/4); // 画面中央にくるように配置
// ●を描画
g.fillStyle = "snow";
g.beginPath();
g.arc(pos.x, pos.y, 20, 0, Math.PI*2, false);
g.fill();
// 画像ファイルを描画
g.drawImage(img, canvas.width/2 - img.width/2, canvas.height/2 - img.height/2);
}
/*
* キャンバスのサイズを端末サイズに合わせて変更
*/
const getSize = ()=>{
// 端末ウインドウ幅に対するウインドウ高さの割合を取得
const windowHeightRatio = window.innerHeight / window.innerWidth;
// 端末のウインドウサイズからキャンバスサイズを再計算する
let width;
let height;
if (windowHeightRatio > canvasHeightRatio) { // 縦長状態(ポートレイト)
width = window.innerWidth;
height = window.innerWidth * (canvas.height / canvas.width);
} else { // 横長状態(ランドスケープ)
width = window.innerHeight * (canvas.width / canvas.height);
height = window.innerHeight;
}
// 現在の端末でキャンバスを表示する際のサイズを設定
canvas.style.width = `${width}px`;
canvas.style.height = `${height}px`;
console.log(`キャンバス表示サイズ w:h = ${width}px:${height}px`);
// 元キャンバス(canvas.height)に対する表示サイズ(height)の大きさ割合を計算(正しいタッチ座標の取得に利用)
resolutionRatio = height / canvas.height;
console.log("resolutionRatio = " + resolutionRatio);
}
// 端末サイズが変更されたときのイベント処理
window.addEventListener("resize", getSize, false);
/*
* ゲームのメイン処理
*/
const GameMain = () =>{
drawCanvas();
// フレーム再描画
requestAnimationFrame(GameMain);
}
/*
* 起動時の処理
*/
window.addEventListener("load", ()=>{
// キャンバス取得
canvas = document.querySelector("#canvas");
g = canvas.getContext("2d"); // コンテキスト:描画対象
// キャンバスの幅に対する高さの割合を取得
canvasHeightRatio = canvas.height / canvas.width;
// キャンバス文字描画設定
g.font = "normal 24px Roboto"; // フォントサイズ・フォント種類 設定
g.textBaseline = "top"; // テキスト描画時のベースライン
// タッチイベント設定
canvas.addEventListener("touchmove", touchMoveListener, false);
// 画像ファイルを読み込む
img = new Image();
img.src = "https://dianxnao.com/public/assets/cat.png";
// 画像読み込みが完了してから開始
img.addEventListener("load", ()=>{
console.log("画像読み込み完了!");
getSize(); // 端末サイズチェック
GameMain(); // ゲームループ開始
}, false);
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment