【问题标题】:Events attached to object inside canvas附加到画布内对象的事件
【发布时间】:2015-09-09 22:03:51
【问题描述】:

我有简单的画布代码,在画布上绘制矩形

var x=document.getElementById("canvas");
var ctx=x.getContext("2d");
ctx.rect(20,20,150,100);
ctx.stroke();

是否可以在所述矩形上添加 eventListener?例如,如果我点击矩形,它会变成红色。

【问题讨论】:

标签: javascript canvas html5-canvas dom-events


【解决方案1】:

地区

根据您对各种旧浏览器的支持程度,您可以通过 Firefox 和 Chrome 中的标志启用 addHitRegion()(在编写本文时):

Firefox: about:config -> 搜索“hitregions”并设置为 true
Chrome:chrome://flags/ -> 启用实验性画布功能

这是唯一将直接与事件系统集成的技术。不过,我还不建议将它用于生产,而且 AFAIK 也没有用于它的 polyfill - 但要展示它的易用性:

var x=document.getElementById("canvas");
var ctx=x.getContext("2d");
ctx.rect(20,20,150,100);
ctx.addHitRegion({id: "demo"});   // enable in flags in Chrome/Firefox
ctx.stroke();

x.addEventListener("click", function(e) {
  if (e.region && e.region === "demo") alert("Hit!");
})
<canvas id="canvas"></canvas>

路径:isPointInPath

其他技术需要手动实现命中检测机制。一种是使用isPointInPath()。您只需一一重建您想要测试的路径,然后针对它运行(调整后的)x/y 鼠标坐标:

var x=document.getElementById("canvas");
var ctx=x.getContext("2d");
generatePath();
ctx.stroke();

x.addEventListener("click", function(e) {
  var r = this.getBoundingClientRect(),
      x = e.clientX - r.left,
      y = e.clientY - r.top;
  
  // normally you would loop through your paths:
  generatePath();
  if (ctx.isPointInPath(x, y)) alert("Hit!");
})

function generatePath() {
  ctx.beginPath();          // reset path
  ctx.rect(20,20,150,100);  // add region to draw/test
}
<canvas id="canvas"></canvas>

路径:Path2D 对象

对于后一个示例,还有新的 Path2D 对象可以自己保存路径 - 这里的优点是您不需要重建路径,只需使用 x/y 传入路径对象到isPointInPath() 方法。

问题是 Path2D 是 not supported in all browsers yet,但是有这个 polyfill 可以为你解决这个问题,

var x=document.getElementById("canvas");
var ctx=x.getContext("2d");

var path1 = new Path2D();
path1.rect(20,20,150,100);  // add rect to path object

ctx.stroke(path1);

x.addEventListener("click", function(e) {
  var r = this.getBoundingClientRect(),
      x = e.clientX - r.left,
      y = e.clientY - r.top;
  
  // normally you would loop through your paths objects:
  if (ctx.isPointInPath(path1, x, y)) alert("Hit!");
})
<canvas id="canvas"></canvas>

手动检查边界

当然,还有使用手动边界检查的旧技术。这将适用于所有浏览器。这里建议做的事情是创建包含边界的对象,也可以用来渲染它。这通常会将您限制在矩形区域 - 更复杂的形状将需要更复杂的算法(例如 isPointInPath() 嵌入)。

var x=document.getElementById("canvas");
var ctx=x.getContext("2d");
ctx.rect(20,20,150,100);
ctx.stroke();

x.addEventListener("click", function(e) {
  var r = this.getBoundingClientRect(),
      x = e.clientX - r.left,
      y = e.clientY - r.top;
  
  // normally you would loop through your region objects:
  if (x >= 20 && x < 20+150 && y >= 20 && y < 20+100) alert("Hit!");
})
&lt;canvas id="canvas"&gt;&lt;/canvas&gt;

【讨论】:

  • 这是一个很好的答案!非常有用和有用。谢谢!
  • 如果可以的话,我会给予更多的支持,这太棒了! ...只是一个说明:我认为第一个 sn-p 有问题
  • @WashingtonGuedes 没有错,但如前所述,您需要通过 Firefox(about:config -> 搜索“hitregions”)和 Chrome(chrome://flags/ -> Enable实验画布功能)
  • @WashingtonGuedes 没问题,感谢您的支持。我更新了答案以使这一步更加清晰。
【解决方案2】:

形状和路径作为副作用被绘制到画布上,因此没有元素可以添加事件监听器;但是,您可以将事件侦听器添加到整个画布或与画布共享位置的元素,然后单击它时用矩形重绘画布,但红色(或其他任何更改)。 (确保在使用.clearRect() 方法重绘之前清除画布)。

【讨论】:

    【解决方案3】:

    如果您在画布上绘制某些东西,则绘制的形状不是 javascript 对象,而是会更改画布所处的特定状态。因此,您不能将事件侦听器附加到它,而应该附加事件到画布本身。

    然后您的 javascript 可以检查点击的坐标,并确定它是否在矩形内。请记住,如果您在矩形或形状上绘制一些东西,则必须调整代码以检查形成的新区域。如果不是矩形,您可能还会发现很难检查该区域,但仍然可以。

    如果要将矩形重绘为红色,则应重新绘制画布,更改重新绘制的新矩形的颜色(矩形不是对象,因此无法直接更改颜色)。这还需要重新绘制画布上的所有其他形状。

    【讨论】:

      猜你喜欢
      • 2016-12-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-31
      • 2020-01-13
      • 2016-03-14
      • 2013-01-13
      • 2012-08-24
      相关资源
      最近更新 更多