我有一个名为Box的画布“对象”,当鼠标悬停在它上面时我需要检测。
我有一个这个对象的draw()方法,我使用的是isPointInPath()方法,但只有在光标位于最后一个路径时才会改变。有什么建议吗?
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';
};
答案 0 :(得分:5)
context.isPointInPath
仅测试最后定义的路径(来自最后一个context.beginPath)。
因此,您必须单独测试每个形状路径:
“重新定义”第一个形状。重新定义意味着重新发出第一个形状的路径命令 - 但您不需要实际描边()或填充()第一个形状。
使用isPointInPath测试鼠标是否在第一个形状内。
继续测试第二,第三,......最后一个形状。
顺便说一句,如果你的所有形状都是矩形,你可以使用数学来测试鼠标是否在任何矩形内:
var isInside=(
mouseX>=RectX &&
mouseX<=RectX+RectWidth &&
mouseY>=RectY &&
mouseY<=RectY+RectHeight
);
答案 1 :(得分:5)
您可以将每个路径存储在数组或对象中以便以后访问它们。
通常,您需要创建Path2D
。 (使用前请检查浏览器支持)。
这是一个非常简单的六边形网格来演示这个: 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.top;
let y = e.pageY - bound.left;
paths.forEach((path, index) => {
if ($.isPointInPath(path, x, y)) {
console.log(index);
}
});
});
document.body.appendChild(C);