Saqib Saqib - 3 months ago 7
jQuery Question

How I can find which grid square element I clicked in HTML5 canvas

I have drawn a grid in html5 canvas using StrokeLineX and StrokeLineY. I want to highlight the particular square/rectangle when I click on it in the grid.
I have tried using math.floor to define an index for a space but as soon as the width or height increases it starts giving different answers. I have tried too many times before finally posting it here.
Here is the code.

var canvas = document.getElementById("myCanvas");
canvas.addEventListener('click', on_canvas_click, false);
var ctx = canvas.getContext("2d");

var tray_length = 800;
var tray_depth = 800;
var boxHeight = 50;
var boxWidth = 50;

var canvas_X = tray_length;
var canvas_Y = tray_depth;

var box_x_pixels = canvas_X/no_of_columns;
var box_y_pixels = canvas_Y/no_of_rows;

// Drawing the grid
for (var y = boxWidth; y < canvas_Y; y += boxWidth) {
strokeLineX(ctx, y);
}

for (var x = boxHeight; x < canvas_X; x += boxHeight) {
strokeLineY(ctx, x);

}

function strokeLineX(ctx, y) {
ctx.beginPath();
ctx.strokeStyle = 'green';
ctx.moveTo(0, y);
ctx.lineTo(canvas_X, y);
ctx.stroke();
ctx.closePath();
}



function strokeLineY(ctx, x) {
ctx.beginPath();
ctx.strokeStyle = 'red';
ctx.moveTo(x, 0);
ctx.lineTo(x, canvas_Y);
ctx.stroke();
ctx.closePath();
}

function on_canvas_click(ev) {
var x = ev.pageX - canvas.offsetLeft;
var y = ev.pageY - canvas.offsetTop;

console.log(x+":"+y);
var coordinateDisplay = "x=" + x + ", y=" + y;

if (y>= 0 && y <= y+boxHeight ) {

var indexOfX = Math.floor(x/boxWidth); //divide on width and round off
var indexOfY = Math.floor(y/boxHeight);
// alert('You clicked bar index: ' + indexOfX+"-"+indexOfY);


ctx.fillRect="green";
ctx.rect(x,y,box_x_pixels,box_y_pixels);
ctx.stroke();

console.log(indexOfX + "-" + indexOfY);


}


}

Answer

In on_canvas_click change the following:

Instead of

    ctx.fillRect="green";

do:

    ctx.fillStyle="green";

And instead of:

    ctx.rect(x,y,box_x_pixels,box_y_pixels);

do:

    ctx.fillRect(boxWidth*indexOfX, boxHeight*indexOfY, boxWidth, boxHeight);

... and you don't need:

    ctx.stroke();

Here is a working snippet with those changes applied, but also with some simplifications which are unrelated to your problem:

  • Removal of unused variables;
  • Use of one function to draw lines, instead of two;
  • Use of canvas.width and canvas.height properties;
  • Drawing grid lines also on the outer grid boundaries

var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
var boxHeight = 50;
var boxWidth = 50;
var canvas_X = canvas.width;
var canvas_Y = canvas.height;

canvas.addEventListener('click', on_canvas_click, false);

// Drawing the grid
for (var y = 0; y <= canvas_Y; y += boxWidth) {
    strokeLine(ctx, 0, y, canvas_X, y, 'green');
}

for (var x = 0; x <= canvas_X; x += boxHeight) {
    strokeLine(ctx, x, 0, x, canvas_Y, 'red');
}

function strokeLine(ctx, x0, y0, x1, y1, color) {
    ctx.beginPath();
    ctx.strokeStyle = color;
    ctx.moveTo(x0, y0);
    ctx.lineTo(x1, y1);
    ctx.stroke();
    ctx.closePath();
}

function on_canvas_click(ev) {
    var x = ev.pageX - canvas.offsetLeft;
    var y = ev.pageY - canvas.offsetTop;
    if (y>= 0 && y <= y+boxHeight ) {    
        var indexOfX = Math.floor(x/boxWidth); //divide on width and round off
        var indexOfY = Math.floor(y/boxHeight);
        ctx.fillStyle="green";
        ctx.fillRect(boxWidth*indexOfX, boxHeight*indexOfY, boxWidth, boxHeight);
    }
}
<canvas id="myCanvas" width="600" height="200"></canvas>