JavaScript:クリックで格子状のマス目番号を取得する

JavaScript

画面を格子状に区切ってクリックした位置のマス目番号を取得したいときがあります。
キャンバス上でクリックしたマウス座標からマス目番号を取得するサンプルを紹介します。

サンプルをみる

クリックしたセル番号とマウス座標は、コンソールに表示されます。
F12キーでConsole表示させてから確認してください。

実行イメージ

考え方

例として、キャンバスに描画した画像を3×3のマス目に区切って内部的に0~8まで9つの番号がついている場合を考えます。

イメージ

画像は480×480ピクセルの正方形画像を使っています。
3×3の格子状に区切ると1セルが160×160ピクセルとなります。

1セルのピクセルサイズ160と1辺のセル数3、そしてクリックしたマウス座標(x、y)を使えば、0から8までのマス目番号は以下の式で取得できます。

(x / 160) + 3 * (y / 160); 

実際のJavaScriptプログラムでは割り算の結果を小数点以下切り捨ての整数として次のようなコードで実現しています。(pos.x, pos.yがクリックしたマウス座標、BLK_SIZE, CELL_SIZEは定数でそれぞれ160と3を表している)

// マウス座標からタッチしたセル番号を求める
cellNo = Math.floor(pos.x / BLK_SIZE) + CELL_SIZE * (Math.floor(pos.y / BLK_SIZE)); 

このコードの定数部分(BLK_SIZE, CELL_SIZE)を変更すれば、ブロックサイズや1辺のセル数が変わっても対応できると思います。

参考

キャンバス上のマウス座標取得については以下で解説しています。

サンプルのソースコード

サンプルの画像はスタジオジブリ提供の画像を加工して利用させていただいています。

index.html

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="style.css">
    <script src="main.js"></script>
    <title>クリックで格子状のマス目番号を取得する</title>
</head>
<body>
    <div id="wrapper">
        <canvas id="canvas" width="480" height="480"></canvas>
    </div>
</body>
</html>

style.css

/* style.css */
@charset "utf-8";

*{
    margin: 0;
    padding: 0;
}

body{
    font-size: 18pt;
}
 
#wrapper{
    display: grid;
    width: 480px;
    height: auto;
}

main.js

// main.js

let canvas = null;      // キャンバス
let g = null;           // コンテキスト
let image;              // 読み込む画像
let pos = {x: 0, y: 0};   // キャンバス上のタッチ座標

const $id = (id) => { return document.getElementById(id); };    // DOM取得用
const IMG_FILE = "majo024_480.jpg";
const IMG_SIZE = 480;   // 画像サイズ
const BLK_SIZE = 160;   // 1ブロックのサイズ
const CELL_SIZE = IMG_SIZE / BLK_SIZE;  // マス目サイズ

// 画像を描画
function draw(){
    g.drawImage(image, 0, 0);
    
    // 枠線描画
    g.strokeStyle = "#ddd";
    for(let i=0; i<IMG_SIZE; i+=BLK_SIZE){
        for(let j=0; j<IMG_SIZE; j+=BLK_SIZE){
            g.strokeRect(i, j, BLK_SIZE, BLK_SIZE);
        }
    }
}


// タッチ時のイベント処理
function touchEventListener(e){
    // マウス座標を取得
    const rect = e.target.getBoundingClientRect();
    pos.x = e.clientX - rect.left;
    pos.y = e.clientY - rect.top;

    // マウス座標からタッチしたセル番号を求める
    cellNo = Math.floor(pos.x / BLK_SIZE) + CELL_SIZE * (Math.floor(pos.y / BLK_SIZE)); 
    console.log(`cell[${cellNo}] click (x,y) = (${pos.x}, ${pos.y})`);
}

/*
 * 起動時の処理
 */
window.addEventListener("load", function(){
    // キャンバス情報取得
    canvas = $id("canvas");
    g = canvas.getContext("2d");

    // キャンバス上でのイベント処理
    canvas.addEventListener("mousedown", touchEventListener, false);
    
    // 画像情報取得
    image = new Image();
    image.src = IMG_FILE;

    image.addEventListener("load", ()=>{
        console.log("image loaded.");
        draw();
    });

});

コメント

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