向canvas元素添加一个单击事件处理程序,返回单击的x和y坐标(相对于canvas元素),最简单的方法是什么?

不需要传统浏览器兼容性,Safari、Opera和Firefox就可以了。


当前回答

我推荐这个链接 http://miloq.blogspot.in/2011/05/coordinates-mouse-click-canvas.html

<style type="text/css">

  #canvas{background-color: #000;}

</style>

<script type="text/javascript">

  document.addEventListener("DOMContentLoaded", init, false);

  function init()
  {
    var canvas = document.getElementById("canvas");
    canvas.addEventListener("mousedown", getPosition, false);
  }

  function getPosition(event)
  {
    var x = new Number();
    var y = new Number();
    var canvas = document.getElementById("canvas");

    if (event.x != undefined && event.y != undefined)
    {
      x = event.x;
      y = event.y;
    }
    else // Firefox method to get the position
    {
      x = event.clientX + document.body.scrollLeft +
          document.documentElement.scrollLeft;
      y = event.clientY + document.body.scrollTop +
          document.documentElement.scrollTop;
    }

    x -= canvas.offsetLeft;
    y -= canvas.offsetTop;

    alert("x: " + x + "  y: " + y);
  }

</script>

其他回答

首先,正如其他人所说,您需要一个函数来获取canvas元素的位置。这里有一个方法,它比本页上的其他一些方法更优雅。你可以将任何元素传递给它,并获得它在文档中的位置:

function findPos(obj) {
    var curleft = 0, curtop = 0;
    if (obj.offsetParent) {
        do {
            curleft += obj.offsetLeft;
            curtop += obj.offsetTop;
        } while (obj = obj.offsetParent);
        return { x: curleft, y: curtop };
    }
    return undefined;
}

现在计算游标相对于它的当前位置:

$('#canvas').mousemove(function(e) {
    var pos = findPos(this);
    var x = e.pageX - pos.x;
    var y = e.pageY - pos.y;
    var coordinateDisplay = "x=" + x + ", y=" + y;
    writeCoordinateDisplay(coordinateDisplay);
});

注意,我将泛型findPos函数与事件处理代码分开。(本来就应该如此。我们应该尽量让每个函数只执行一个任务。)

offsetLeft和offsetTop的值相对于offsetParent,它可以是某个包装器div节点(或者其他任何东西)。当没有元素包裹画布时,它们是相对于主体的,因此没有要减去的偏移量。这就是为什么我们需要在做其他事情之前确定画布的位置。

类似地,e.pageX和e.pageY给出了光标相对于文档的位置。这就是为什么我们从这些值中减去画布的偏移量来达到真实位置。

定位元素的另一种选择是直接使用e.layerX和e.layerY的值。这种方法不如上面的方法可靠,有两个原因:

当事件不在定位的元素中发生时,这些值也相对于整个文档 它们不是任何标准的一部分

参见http://jsbin.com/ApuJOSA/1/edit?html,output上的演示。

  function mousePositionOnCanvas(e) {
      var el=e.target, c=el;
      var scaleX = c.width/c.offsetWidth || 1;
      var scaleY = c.height/c.offsetHeight || 1;

      if (!isNaN(e.offsetX)) 
          return { x:e.offsetX*scaleX, y:e.offsetY*scaleY };

      var x=e.pageX, y=e.pageY;
      do {
        x -= el.offsetLeft;
        y -= el.offsetTop;
        el = el.offsetParent;
      } while (el);
      return { x: x*scaleX, y: y*scaleY };
  }

嘿,这是在dojo,只是因为它是我已经在一个项目的代码。

如何将其转换回非dojo的普通JavaScript应该是相当明显的。

  function onMouseClick(e) {
      var x = e.clientX;
      var y = e.clientY;
  }
  var canvas = dojo.byId(canvasId);
  dojo.connect(canvas,"click",onMouseClick);

希望这能有所帮助。

现代浏览器现在可以帮你处理这个。Chrome, IE9和Firefox支持这样的offsetX/Y,从点击处理程序传入事件。

function getRelativeCoords(event) {
    return { x: event.offsetX, y: event.offsetY };
}

大多数现代浏览器也支持layerX/Y,但是Chrome和IE使用layerX/Y作为页面点击的绝对偏移量,包括边距、填充等。在Firefox中,layerX/Y和offsetX/Y是等价的,但是offset之前并不存在。所以,为了兼容稍微老一点的浏览器,你可以使用:

function getRelativeCoords(event) {
    return { x: event.offsetX || event.layerX, y: event.offsetY || event.layerY };
}

如果你喜欢简单,但仍然需要跨浏览器功能,我发现这个解决方案最适合我。这是一个简化的@Aldekein的解决方案,但没有jQuery。

function getCursorPosition(canvas, event) {
    const rect = canvas.getBoundingClientRect()
    const x = event.clientX - rect.left
    const y = event.clientY - rect.top
    console.log("x: " + x + " y: " + y)
}

const canvas = document.querySelector('canvas')
canvas.addEventListener('mousedown', function(e) {
    getCursorPosition(canvas, e)
})