如何将 onClick 事件处理程序添加到 Elm 中的 canvas 形状?

How to add an onClick event handler to a canvas shape in Elm?

是否可以向 Graphics.Collage.square 添加 onClick 事件处理程序?

我想知道点击的相对位置。

在 Javascript 中,我可以做类似 this 的事情:

var canvas = document.getElementById('canvas');
var canvasPosition = {
  x: canvas.offsetLeft,
  y: canvas.offsetTop
};

canvas.addEventListener('click', function(event) {
  console.log(event.x - canvasPosition.x, event.y - canvasPosition.y);
}, false);

是否可以在 Elm 中做类似的事情?

示例将不胜感激。

在 Elm 中,使用 Canvas 渲染,您应该使用 Mouse.clicks 信号并对信号的变化做出反应。这是一个可运行的示例,说明它是如何工作的:

import Graphics.Element exposing (Element, show)
import Mouse

clicks : Signal (Int, Int)
clicks =
  Signal.sampleOn Mouse.clicks Mouse.position

main : Signal Element
main =
  Signal.map show clicks

本质上,Mouse.clicks 是我们感兴趣的实际 "events",因此无论何时发生,我们都会 "sample" Mouse.position 信号以获得点击位置。

Signal.sampleOn 产生一个信号,当第一个参数信号(此处为鼠标点击)发生变化时,该信号会更新第二个参数信号(此处为鼠标位置)的值。

现在,为了显示结果,我们还将位置映射到 main 中的 show 函数。

您也可以将此代码粘贴到 http://elm-lang.org/try,编译并尝试单击右侧以查看它是否有效。

我实现了一个proof-of-concept backbuffer test。它很老套,但它可以完成这项工作。

如果您不喜欢这样,您唯一的选择是找到鼠标点击位置(这涉及到从鼠标左上角原点的非常烦人的转换,y 下降到 Graphics.Collage 的居中origin, y is up),然后做几何碰撞检测。这对于圆形和轴对齐的矩形来说还算不错,但我明白了,你想要一个通用的解决方案。

您也可以考虑使用 elm-svg,它具有典型的 DOM 事件,例如 mouseenter,尽管我不确定事件派发的可靠性如何,例如凸形。或者您可以完全放弃 Elm(嗅探)并使用 D3.js 和 SVG。