isPointInPath(x,y) 面向的对象是路径,所以对文字、图片、fillRect()、strokeRect()不好使,用ctx.stroke()替代strokeRect(),用ctx.fill()替代fillRect();
在ctx.beginPath() 之后,所绘制的所有路径都会被添加到这个路径集合里,isPointInPath(x,y) 方法判断的就是x、y 点是否在这个路径集合的所有路径里
<div class="box">
<canvas
id="canvas"
width="500"
height="400"
style="border: 1px solid #999"
></canvas>
</div>
var c = document.getElementById("canvas");
var ctx = c.getContext("2d");
const canvasInfo = canvas.getBoundingClientRect();
console.log(canvasInfo);
//正方形
function drawSquare() {
ctx.beginPath();
ctx.moveTo(10, 10);
ctx.lineTo(10, 50);
ctx.lineTo(50, 50);
ctx.lineTo(50, 10);
ctx.fillStyle = "black";
ctx.closePath();
ctx.stroke();
ctx.fill();
}
//圆形
function drawCircle() {
ctx.beginPath();
ctx.arc(100, 100, 50, 0, 2 * Math.PI);
ctx.fillStyle = "blue";
ctx.fill();
ctx.closePath();
}
// 三角形
function drawTriangle() {
ctx.beginPath();
ctx.moveTo(150, 150);
ctx.lineTo(200, 50);
ctx.lineTo(250, 150);
ctx.closePath();
ctx.stroke();
}
//贝塞尔曲线
function drawBezier() {
ctx.beginPath();
ctx.moveTo(240, 200);
ctx.bezierCurveTo(110, 110, 199, 278, 300, 379);
ctx.lineTo(400, 100);
ctx.closePath();
ctx.stroke();
}
let drawArray = [];
drawArray.push(drawSquare, drawCircle, drawTriangle, drawBezier);
drawArray.forEach((fn) => fn());
如果直接使用isPointInPath对点击的坐标点位置判断,会因为绘制图形时使用beginPath进行重置,而导致只有最后一个图形被点击时才会显示为true,所以点击时我们采用先清空画布再循环画每个图形,这样只要是图形内的坐标点就会被识别
canvas.addEventListener("click", function (e) {
const canvasInfo = canvas.getBoundingClientRect();
const x = e.clientX - canvasInfo.left;
const y = e.clientY - canvasInfo.top;
const res = ctx.isPointInPath(x, y);
ctx.clearRect(0, 0, 500, 400);
// 遍历绘制图形
for (var i = drawArray.length; i--; ) {
drawArray[i]();
// 每绘制一个图形就判断一次当前鼠标的坐标是否在这个图形上,然后进行自定义操作
if (ctx.isPointInPath(x, y)) {
...
}
}
});