I have a canvas "object" named Box and I need detect when mouse is over it.
I have a draw() method for this object which I use isPointInPath() method, but only change when the cursor is on the last path. Any suggestions?
Box.prototype.draw = function() {
this.ctx.beginPath();
this.ctx.moveTo(this.matrix.p1.x, this.matrix.p1.y);
this.ctx.lineTo(this.matrix.p2.x, this.matrix.p2.y);
this.ctx.lineTo(this.matrix.p3.x, this.matrix.p3.y);
this.ctx.lineTo(this.matrix.p4.x, this.matrix.p4.y);
this.ctx.lineTo(this.matrix.p1.x, this.matrix.p1.y);
this.ctx.closePath();
this.ctx.fillStyle = 'rgba(255, 255, 255, 0.1)';
this.ctx.fill();
if (this.ctx.isPointInPath(mouse.x, mouse.y)) {
this.canvas.style.cursor = 'pointer';
this.ctx.fillStyle = 'rgba(0, 0, 255, 0.5)';
this.ctx.fill();
return;
}
this.canvas.style.cursor = 'default';
};
You can store each path in an array or object to access them later.
In general you need to create a Path2D. (check browser support before using).
Here's a really simple grid of hexagons to demonstrate this: http://codepen.io/pixelass/pen/37445407893ef783e414ce136af5633a
const C = document.createElement('canvas');
const $ = C.getContext('2d');
const rows = 5;
const cols = 5;
var side = 50;
C.width = cols * side * Math.sqrt(3);
C.height = rows * 1.5 * side;
const paths = [];
var dy = -1;
for (let i = 0; i < (rows + 1) * (cols + 1); i++) {
let dx = i % (cols + 1);
dy += dx ? 0 : 1;
dx += dy % 2 ? -.5 : 0;
let cx = dx * (side * Math.sqrt(3)) + side / 2 * Math.sqrt(3);
let cy = (dy - .5) * (side * 1.5) + side;
let path = new Path2D();
for (let j = 0; j < 6; j++) {
let x = Math.cos(Math.PI / 3 * j + Math.PI / 6) * side + cx;
let y = Math.sin(Math.PI / 3 * j + Math.PI / 6) * side + cy;
if (j) {
path.lineTo(x, y);
} else {
path.moveTo(x, y);
}
}
path.closePath();
$.fillStyle = `hsl(${10*i},50%,50%)`;
$.fill(path);
paths.push(path);
}
C.addEventListener('mousemove', e => {
let bound = C.getBoundingClientRect();
let x = e.pageX - bound.left;
let y = e.pageY - bound.top;
paths.forEach((path, index) => {
if ($.isPointInPath(path, x, y)) {
console.log(index);
}
});
});
document.body.appendChild(C);
context.isPointInPath only tests the very last path defined (from the last context.beginPath).
So you must individually test each of your shape paths:
"Redefine" the first shape shape. Redefine means reissuing the first shape's path commands--but you don't need to actually stroke() or fill() the first shape.
Test if the mouse is inside the first shape using isPointInPath.
Continue testing the second, third, ... last shape.
BTW, if all of your shapes are rectangles you can use math to test if the mouse is inside any rectangle:
var isInside=(
mouseX>=RectX &&
mouseX<=RectX+RectWidth &&
mouseY>=RectY &&
mouseY<=RectY+RectHeight
);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With