2
  1. 我想这不起作用,因为画布正在绘制矢量的位图(并且位图不是路径)。
  2. 即使它确实有效,位图也可能总是有一个矩形许可器。

有没有办法isPointInPath在使用时利用类似的东西drawImage

例子:

  • 顶部画布是使用绘制的drawImageisPointInPath但不起作用。
  • 底部画布是使用arcisPointInPath作品绘制的。

我的证明的链接

** 编辑 **

我在一个画布上画了一个圆圈,并isPointInPath用来查看鼠标指针是否在圆圈内(在我的示例中为底部画布)。我还使用 .将底部画布“复制”到顶部画布drawImage。请注意,这isPointInPath在顶部画布上不起作用(很可能是由于我上面提到的原因)。是否有一种解决方法可以用于任何类型的路径(或位图)?

4

4 回答 4

4

画布上下文有一个隐藏的东西,称为当前路径。ctx.beginPathctx.lineTo创建此路径。

当您调用ctx.stroke()ctx.fill()画布描边或填充该路径时。

即使在描边或填充之后,路径仍然存在于上下文中。

这条路径是唯一可以isPointInPath测试的东西。

如果您想测试是否在您绘制的图像或使用 绘制的矩形中,ctx.fillRect()则使用内置方法是不可能的。

通常,您希望使用自己编写(或从其他人那里获得)的 is-point-in-rectangle 函数。

如果您正在寻找如何对图像进行像素完美(而不仅仅是图像矩形)命中检测,这里讨论了各种方法:使用 Canvas 进行像素完美 2D 鼠标拾取

于 2011-12-24T00:22:34.433 回答
1

您可以尝试重新实现ctx.drawImage()以始终在图像本身后面绘制一个框,如下所示(JSFiddle 示例):

ctx.customDrawImage = function(image, x, y){
    this.drawImage(image, x, y);
    this.rect(x, y, image.width, image.height);
}
var img1 = new Image();
img1.onload = function(){
var x = y = 0;
ctx.drawImage(img1, x, y);
console.log(ctx.isPointInPath(x + 1, y + 1));

x = 1.25 * img1.width;
ctx.customDrawImage(img1, x, y);
console.log(ctx.isPointInPath(x + 1, y + 1));

注意:如果你不小心,你可能会得到像矩形出现在图像上的副作用,或者从后面渗出。

于 2011-12-24T00:33:00.570 回答
0

对我来说,画布移动后 isPointInPath 失败。所以,我用:

mouseClientX -= gCanvasElement.offsetLeft; mouseclientY -= gCanvasElement.offsetTop;

于 2017-05-07T05:13:22.733 回答
0

我遇到了更多挑战,因为我的画布元素可以重新缩放。所以首先当我绘制图形时,在我的例子中,我将它们与名称一起保存在一个数组中并绘制它们:

      if (this.coInit == false)
      {
        let co = new TempCO ();
        co.name= sensor.Name;
        co.path = new Path2D();
        co.path.arc(c.X, c.Y, this.radius,  0, 2 * Math.PI);
        this.coWithPath.push(co);
      }
      let coWP = this.coWithPath.find(c=>c.name == sensor.Name);
      this.ctx.fillStyle = color;
      this.ctx.fill(coWP.path);

然后在鼠标事件中,我循环遍历项目并检查单击事件是否在路径中。但我还需要根据调整后的画布重新调整鼠标坐标:

getCursorPosition(event) {
  const rect = this.ctx.canvas.getBoundingClientRect();
  const x = ((event.clientX - rect.left ) / rect.width) * this.canvasWidth;
  const y = ((event.clientY - rect.top) / rect.height) * this.canvasHeight;
  this.coWithPath.forEach(c=>{

    if (this.ctx.isPointInPath(c.path, x, y))
    {
      console.log("arc is hit", c);
      //Switch light
    }
  });
}

所以我得到了画布的当前大小并将点重新缩放到原始大小。现在它起作用了!

这就是 TempCO 的样子:

export class TempCO
{
  path : Path2D;
  name : string;
}
于 2020-06-15T14:05:49.487 回答