JavaScript:マウスホバーしているセル位置を求める

JavaScript

パズルゲームなどの格子状ステージで、現在マウスホバー中のセル位置を視覚的に変化させる。

イメージ

ソースコード

index.html

<!DOCTYPE html>
<html lang="ja">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>OTIMONO(03マウスホバーしているセル位置の色が変わる)</title>
	<style>
		*{
			margin: 0;
			padding: 0;
		}
		body{
			margin: 0 50px;
		}
	</style>
	<script src="main.js" type="text/javascript"></script>
</head>
<body>
	<canvas id="canvas" width="512" height="512"></canvas>
</body>
</html>

main.js

// キャンバスでのマウスイベントの状態を表示する
let canvas = null;
let g = null;
let pos = {x:0, y:0};		// キャンバス上のマウス座標
let cpos = {x:0, y:0};		// マウス座標から得られるセル位置
let isMouseDown = false;	// マウスを押しているか?

const CELL_SIZE = 64;							// パズルキャラのサイズ(64x64ピクセル)
const ROW_SIZE = COLUMN_SIZE = 512 / CELL_SIZE;	// 行と列に何個並べるか?
const CELL_LENGTH = ROW_SIZE * COLUMN_SIZE;		// パズルキャラの数

/*
 * マウスを動かしている時の処理
 */
const mouseMoveListener = (e) => {
	// オフセット位置:キャンバスがブラウザの左上からどれくらいの位置にあるか?(rect.left, rect.top)
	const rect = e.target.getBoundingClientRect();

	// e.clientXとe.clientYはブラウザ左上からのキャンバスクリック位置なのでオフセット分を引くとキャンバス上の座標が分かる
	pos.x = e.clientX - rect.left;
	pos.y = e.clientY - rect.top;

	// マウス座標からセル位置を求める
	cpos.x = Math.floor(pos.x / CELL_SIZE);
	cpos.y = Math.floor(pos.y / CELL_SIZE);

	drawMouseInfo();
};

/*
 * マウスボタンを押した時の処理
 */
const mouseDownListener = () => {
	isMouseDown = true;
	drawMouseInfo();
};

/*
 * マウスボタンを離した時の処理
 */
const mouseUpListener = () => {
	isMouseDown = false;
	drawMouseInfo();
};

/*
 * キャンバスにマウス情報を表示
 */
const drawMouseInfo = ()=> {
	// 表示する文字列を設定
	const mouseDownString = isMouseDown ? "押した!" : "離した!";
	const txtPos = `x: ${pos.x} y:${pos.y} ${mouseDownString}`;

	// マウス情報を表示する
	g.fillStyle = "#555";
	g.fillText(txtPos, 150, canvas.height/2);
}

/*
 * ステージを表示
 */
const drawStage = ()=> {
	let x = 0, y = 0;	// 描画するセル位置
	let color1 = "pink", color2 = "skyblue";	// 市松模様のステージ色

	for(i=0; i<CELL_LENGTH; i++){
		// 1段下がると先頭の色を入れ替える
		if(i % 8 == 0) [color1, color2] = [color2, color1];
		// 格子状にブロックを表示
		x = i % COLUMN_SIZE;			// x方向セル位置
		y = Math.floor(i / ROW_SIZE);	// Y方向セル位置

		// 色を交互に設定
		bgColor = (i % 2 == 0) ? color1: color2;
		g.fillStyle = bgColor;
		g.fillRect(x * CELL_SIZE, y * CELL_SIZE, CELL_SIZE, CELL_SIZE);
	}
}

/*
 * カーソルを表示
 */
const drawCursor = ()=> {
	g.fillStyle = "rgba(128, 128, 128, 0.5)";	// グレー色で透過
	g.fillRect(cpos.x * CELL_SIZE, cpos.y * CELL_SIZE, CELL_SIZE, CELL_SIZE);
}

/*
 * ゲームのメイン処理(今は少ない)
 */
const GameMain = () =>{
	// キャンバスクリア
	g.clearRect(0, 0, canvas.width, canvas.height);
	// ステージ描画
	drawStage();
	// カーソル描画
	drawCursor();
	// マウス情報表示
	drawMouseInfo();
	// フレーム再描画
	requestAnimationFrame(GameMain);
}

/*
 * 起動時の処理
 */
window.addEventListener("load", ()=>{
	canvas = document.getElementById("canvas");
	g = canvas.getContext("2d");
	g.font = "bold 24px System";	// フォントサイズ・フォント種類 設定

	// マウスイベント設定
	canvas.addEventListener("mousemove", mouseMoveListener, false);
	canvas.addEventListener("mousedown", mouseDownListener, false);
	canvas.addEventListener("mouseup", mouseUpListener, false);

	// ゲームのメイン処理呼び出し(ゲーム開始)
	GameMain();
});

コメント

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