如何添加一个简单的onClick事件处理程序到canvas元素?

我是一位经验丰富的Java程序员,但是大约十年来我首次查看了一些JavaScript / HTML5的东西。 我完全沉迷于最简单的事情。

作为一个例子,我只是想画一些东西,并添加一个事件处理程序。 我确信我在做一些愚蠢的事情,但我已经搜遍了,没有什么build议(例如,这个问题的答案: 添加onclick属性inputJavaScript )的作品。 我正在使用Firefox 10.0.1。 我的代码如下。 你会看到几个注释行,每个行的结尾是什么(或什么不)发生的描述。

这里有什么正确的语法? 我要疯了!

<html> <body> <canvas id="myCanvas" width="300" height="150"/> <script language="JavaScript"> var elem = document.getElementById('myCanvas'); // elem.onClick = alert("hello world"); - displays alert without clicking // elem.onClick = alert('hello world'); - displays alert without clicking // elem.onClick = "alert('hello world!')"; - does nothing, even with clicking // elem.onClick = function() { alert('hello world!'); }; - does nothing // elem.onClick = function() { alert("hello world!"); }; - does nothing var context = elem.getContext('2d'); context.fillStyle = '#05EFFF'; context.fillRect(0, 0, 150, 100); </script> </body> 

当你绘制一个canvas元素,你只是在即时模式下绘制一个位图。

除了使用的像素和颜色之外,绘制的元素 (形状,线条,图像)都没有表示。

因此,要在canvas 元素 (形状)上获得点击事件,您需要捕获canvas元素上的click事件,并使用一些math运算来确定哪个元素被点击,只要存储元素的width / height和x / y抵消。

要将click事件添加到您的canvas元素,请使用…

 canvas.addEventListener('click', function() { }, false); 

确定点击了什么元素

 var elem = document.getElementById('myCanvas'), elemLeft = elem.offsetLeft, elemTop = elem.offsetTop, context = elem.getContext('2d'), elements = []; // Add event listener for `click` events. elem.addEventListener('click', function(event) { var x = event.pageX - elemLeft, y = event.pageY - elemTop; // Collision detection between clicked offset and element. elements.forEach(function(element) { if (y > element.top && y < element.top + element.height && x > element.left && x < element.left + element.width) { alert('clicked an element'); } }); }, false); // Add element. elements.push({ colour: '#05EFFF', width: 150, height: 100, top: 20, left: 15 }); // Render elements. elements.forEach(function(element) { context.fillStyle = element.colour; context.fillRect(element.left, element.top, element.width, element.height); });​ 

jsFiddle 。

此代码将一个click事件附加到canvas元素,然后将一个形状(在我的代码中称为一个element )推送到一个elements数组。 你可以在这里添加尽可能多的。

创build对象数组的目的是让我们可以稍后查询它们的属性。 在所有的元素被压入数组之后,我们循环遍历并根据它们的属性来渲染每一个元素。

触发click事件时,代码循环遍历元素,并确定点击是否覆盖了elements数组中的任何elements 。 如果是这样的话,它会触发一个alert() ,这个alert()很容易被修改来做一些事情,比如删除数组项,在这种情况下,你需要一个单独的渲染函数来更新canvas

为了完整性,为什么你的尝试不工作…

 elem.onClick = alert("hello world"); // displays alert without clicking 

这是将alert()的返回值分配给elemonClick属性。 它立即调用alert()

 elem.onClick = alert('hello world'); // displays alert without clicking 

在JavaScript中, '"在语义上是相同的,词法分析器可能使用['"]作为引号。

 elem.onClick = "alert('hello world!')"; // does nothing, even with clicking 

您正在将一个string分配给elemonClick属性。

 elem.onClick = function() { alert('hello world!'); }; // does nothing 

JavaScript是区分大小写的。 onclick属性是附加事件处理程序的古老方法。 它只允许将一个事件附加到该属性,并且在序列化HTML时该事件可能会丢失。

 elem.onClick = function() { alert("hello world!"); }; // does nothing 

再次, ' === "

您也可以将DOM元素(如div放在canvas顶部,代表您的canvas元素并以相同的方式放置。

现在,您可以将事件监听器附加到这些div并运行必要的操作。

作为alex的答案的替代:

您可以使用SVG绘图而不是Canvas绘图。 在那里你可以直接添加事件到绘制的DOM对象。

看例如:

使用onclick可以使svg图像对象点击,避免绝对定位

亚历克斯答案是相当整洁,但使用上下文旋转时,可能很难跟踪x,y坐标,所以我做了一个演示如何跟踪这一点。

基本上我正在使用这个function,给它的angular度和在绘制对象之前在那个天使行进的距离的数量。

 function rotCor(angle, length){ var cos = Math.cos(angle); var sin = Math.sin(angle); var newx = length*cos; var newy = length*sin; return { x : newx, y : newy }; }