【问题标题】:How to implement event system in HTML5 Canvas(with transformation?如何在 HTML5 Canvas 中实现事件系统(带转换?
【发布时间】:2015-04-29 20:17:08
【问题描述】:

假设我这样做了:

  • 保存画布并应用变换,比如A
  • 在点(x, y) 绘制一个形状(矩形等),给它一个id,"pointer-#{itoa}"
  • (随机重复,这样我们会得到一堆保存的画布状态)
  • 恢复画布状态
  • 随机重复

现在有一个点击事件,我想找出被点击的那个形状的 ID。有什么工具可以做到这一点吗?


我想提一下,我正在尝试实现基于 Canvas(项目名称 Quamolit)的 HTML 子集,以更好地支持过渡。并且在一些变换之后找出点击了哪个元素成为一个大问题。

同时,我试图让 Quamolit 中的每个元素都以一些标量(translateX、translateY、旋转、缩放)来描述,以使它们易于插值。

【问题讨论】:

  • 画布内没有对象,只是混合在一起的像素。您必须自己实现对象和事件的逻辑。对于事件,也许我的Eventor(一对多)或Harbour(端口,多对一)可以在事件部分为您提供帮助......
  • @KenFyrstenberg 我认为“事件系统”是指框架正在处理点击的整个事情,而困难的部分是在转换之后,我几乎无法找出点击的像素属于哪个对象。 Eventor 好像是 EventEmitter 什么的?
  • 是的,有很多库可以帮助跟踪和“移动”画布上的单个绘图。请记住,画布上的单个绘图不能真正移动。所发生的情况是画布被清除,并且绘图被重新绘制到新的所需位置。由于 SO 并不意味着作为库推荐的来源,您可以通过谷歌搜索找到许多好的画布库:“html 画布库”。
  • @markE 我想要的库是“react-canvas”。不幸的是,它还不支持转换。我发现fabric.js 确实会拖拽移动。我稍后会研究。

标签: canvas graphics


【解决方案1】:

Canvas 以所谓的“立即模式”绘制,它不跟踪绘制的内容。

但是您可以使用renderingContext.isPointInPath() (https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/isPointInPath) 来测试一个点(即鼠标单击的坐标)是否在路径内。这个函数必须在绘图时使用,所以使用它可能不是一件容易的事,但这是当前实现它的方法。 默认情况下,isPointInPath() 使用零数缠绕规则来检测一个点是否在路径内,这与浏览器用来填充路径的算法相同。

将来会有 HitRegions 可以简化这一点,但这还没有在所有浏览器中实现。 (https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/addHitRegion)

【讨论】:

    【解决方案2】:

    除了ctx.isPointInPath(),我在规范中发现了一个叫Hit Region的东西

    http://www.w3.org/TR/2dcontext/#hit-regions

    正如 MDN 上所描述的,这正是判断正在点击哪个路径的最佳解决方案:

    https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/addHitRegion

    canvas.addEventListener("mousemove", function(event){
      if(event.region) {
        alert("ouch, my eye :(");
      }
    });
    
    // eyes
    ctx.beginPath();
    ctx.arc(70, 80, 10, 0, 2 * Math.PI, false);
    ctx.arc(130, 80, 10, 0, 2 * Math.PI, false);
    ctx.fill();
    ctx.addHitRegion({id: "eyes"});
    

    可以为每个路径指定一个id。单击时,该 ID 将通过event 发送回。

    坏消息是任何浏览器都不完全支持此 API。 Chrome 和 Firefox 支持其中的基本部分。

    【讨论】:

      猜你喜欢
      • 2018-09-18
      • 2011-05-24
      • 2019-05-28
      • 2012-04-06
      • 1970-01-01
      • 2012-01-14
      • 1970-01-01
      • 2011-01-27
      • 2013-04-07
      相关资源
      最近更新 更多