javascript - 附加到 Canvas 内对象的事件

标签 javascript canvas html5-canvas dom-events

我有简单的 Canvas 代码,可以在 Canvas 上绘制矩形

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

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

最佳答案

地区

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

Firefox: about:config -> search "hitregions" and set to true
Chrome: chrome://flags/ -> Enable experimental canvas features

这是唯一直接与事件系统集成的技术。不过,我还不建议将它用于生产环境,而且 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!");
})
<canvas id="canvas"></canvas>

关于javascript - 附加到 Canvas 内对象的事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31014083/

相关文章:

javascript - Phonegap Windows Phone 8 自定义网络字体

javascript - Canvas/Fabric.js .loadFromJSON() 替换整个 Canvas

javascript - 如何在 melonJS 中随时间改变 Sprite 的颜色

javascript - Three.js 寻找屏幕边缘二维投影的位置

javascript - 使用此类的下一个 div 的 jQuery 切换

javascript - 如何将 ng-options 和 ng-select 与 json 一起使用

javascript - 输入时删除默认电话号码示例

javascript - 如何在fabric.js中设置样式

javascript - 在嵌套数组中创建带有 javascript 错误的游戏

html - 如何确保 Canvas 与html中的视频大小相同?