How to add a simple onClick event handler to a canvas element?

I am an experienced Java programmer, but for the first time in several decades I have been looking at JavaScript / HTML5 material. I am completely shocked at what should be the easiest.

As an example, I just wanted to draw something and add an event handler to it. I'm sure I'm doing something stupid, but I was looking for everything and nothing that was suggested (for example, the answer to this question: Add onclick property for input using JavaScript ). I am using Firefox 10.0.1. My code follows. You will see some commented lines, and at the end of each there will be a description of what (or what is not happening).

What is the correct syntax here? I'm going crazy!

<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> 

+75
javascript html5 event-handling canvas onclick
Mar 26 2018-12-12T00:
source share
4 answers

When you draw the canvas element, you just draw the bitmap in immediate mode .

The elements (shapes, lines, images) that are drawn have no representation, except for the pixels that they use and their colors.

Therefore, to get the click event on the canvas element (shape), you need to capture the click events on the canvas HTML element and use some math to determine which element was clicked, provided that you store the elements' width / height and x / y offset.

To add a click event to your canvas element, use ...

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

To determine which item was clicked ...

 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 .

This code attaches the click event to the canvas element, and then pushes one form (called element in my code) into the elements array. You can add as much as you want.

The goal of creating an array of objects is that we can later request their properties. After all the elements have been transferred to the array, we scroll and visualize each based on their properties.

When the click event is fired, the code goes through the elements and determines whether there was a click on any of the elements in the elements array. If so, it fires alert() , which can be easily changed to do something like deleting an array element, in which case you will need a separate rendering function to update the canvas .

For completeness, why your attempts did not work ...

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

This sets the return value of alert() to the onClick elem property. It immediately calls alert() .

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

In JavaScript, the characters ' and " semantically identical, the lexer probably uses ['"] for quotes.

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

You assign a string to the onClick elem property.

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

JavaScript is case sensitive. The onClick property is an archaic method for binding event handlers. It only allows you to bind one event to a property, and the event may be lost when serializing HTML.

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

Again, ' === " .

+136
Mar 26 2018-12-12T00:
source share

You can also place DOM elements, such as div on top of the canvas, that will represent your canvas elements and will be located the same way.

Now you can attach event listeners to these divs and perform the necessary actions.

+2
Mar 31 '16 at 16:22
source share

As an alternative to alex's answer:

You can use an SVG picture instead of a Canvas picture. There you can add events directly to the drawn DOM objects.

see for example:

Create svg image object with onclick avoiding absolute positioning

0
Oct 14 '15 at 12:35
source share

Alex Answer is pretty neat, but using context rotation can be difficult to track the x, y coordinates, so I made a demo showing how to track this.

I mainly use this function and give it the angle and the amount of distance traveled in this angel before drawing the object.

 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 }; } 
0
Jan 24 '17 at 15:55
source share



All Articles