How do I add a simple onClick event handler to a canvas element?
When you draw to a canvas
element, you are simply drawing a bitmap in immediate mode.
The elements (shapes, lines, images) that are drawn have no representation besides the pixels they use and their colour.
Therefore, to get a click event on a canvas
element (shape), you need to capture click events on the canvas
HTML element and use some math to determine which element was clicked, provided you are storing 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 element was clicked...
var elem = document.getElementById('myCanvas'),
elemLeft = elem.offsetLeft + elem.clientLeft,
elemTop = elem.offsetTop + elem.clientTop,
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 a click
event to the canvas
element, and then pushes one shape (called an element
in my code) to an elements
array. You could add as many as you wish here.
The purpose of creating an array of objects is so we can query their properties later. After all the elements have been pushed onto the array, we loop through and render each one based on their properties.
When the click
event is triggered, the code loops through the elements and determines if the click was over any of the elements in the elements
array. If so, it fires an alert()
, which could easily be modified to do something such as remove the array item, in which case you'd need a separate render function to update the canvas
.
For completeness, why your attempts didn't work...
elem.onClick = alert("hello world"); // displays alert without clicking
This is assigning the return value of alert()
to the onClick
property of elem
. It is immediately invoking the alert()
.
elem.onClick = alert('hello world'); // displays alert without clicking
In JavaScript, the '
and "
are semantically identical, the lexer probably uses ['"]
for quotes.
elem.onClick = "alert('hello world!')"; // does nothing, even with clicking
You are assigning a string to the onClick
property of elem
.
elem.onClick = function() { alert('hello world!'); }; // does nothing
JavaScript is case sensitive. The onclick
property is the archaic method of attaching event handlers. It only allows one event to be attached with the property and the event can be lost when serialising the HTML.
elem.onClick = function() { alert("hello world!"); }; // does nothing
Again, ' === "
.
How do I add a onClick event handler to a canvas element (arc)?
You need to redraw the shape before calling the method isPointInPath
.
Ive added to your code a function to detect the mouse position and an other one that draws the element. I hope it helps.
var elements = [];var canvas = document.getElementById("myCanvas");canvas.width = "500";canvas.height = "500";var context = canvas.getContext("2d");
var mouse;
elements.push({ colour: "#112F41", x: 200, y: 240, r: 100, sAngle: 0, eAngle: 2 * Math.PI});
elements.forEach(element => { drawElement(element, context);});
canvas.addEventListener( "click", function(event) { mouse = oMousePos(canvas, event) elements.forEach(function(element) { drawElement(element, context); if(context.isPointInPath(mouse.x, mouse.y)){console.log(mouse)}else{console.log("not in path")} }); }, false);
function drawElement(element, context) { context.strokeStyle = element.colour; context.arc(element.x, element.y, element.r, element.sAngle, element.eAngle); context.lineWidth = 2;
context.stroke();}
function oMousePos(canvas, evt) { var ClientRect = canvas.getBoundingClientRect(); return { //objeto x: Math.round(evt.clientX - ClientRect.left), y: Math.round(evt.clientY - ClientRect.top) }}
canvas { border:1px solid;}
<canvas id="myCanvas"></canvas>
How do I add a onClick event handler to a canvas element and control mouse movement actions?
First, you have to check if your mouse is on the image, and then check if you are trying to drag the image. To do that, you need some events, mousedown
, mouseup
and mousemove
. To check if your mouse pointer is on the image, you have to get the X, Y, width, height
of that image. Final code below.
Some more changes. Image
class has no X
and Y
properties so I had to define variables that will store that data and make some changes to isInside
function.
var canvas = document.createElement('canvas');document.body.appendChild(canvas);var context = canvas.getContext('2d');canvas.width = 300;canvas.height = 300;var upload_image;var imageX, imageY;var mouseX, mouseY;var imageDrag = false;
make_base();
canvas.addEventListener("mousemove", function (evt) { var mousePos = getMousePos(canvas, evt); mouseX = mousePos.x; mouseY = mousePos.y;});
function getMousePos(canvas, event) { var rect = canvas.getBoundingClientRect(); return { x: event.clientX - rect.left, y: event.clientY - rect.top };}
function isInsideImage(rect) { var pos = { x: mouseX, y: mouseY }; return pos.x > imageX && pos.x < imageX + rect.width && pos.y < imageY + rect.height && pos.y > imageY;}
function make_base(){ upload_image = new Image(); imageX = 0; imageY = 0; upload_image.onload = function(){ context.drawImage(upload_image, 0, 0); } upload_image.src = 'https://lh3.googleusercontent.com/-6Zw-hozuEUg/VRF7LlCjcLI/AAAAAAAAAKQ/A61C3bhuGDs/w126-h126-p/eagle.jpg';}
canvas.addEventListener("mousedown", function (evt) { if(isInsideImage(upload_image)) { imageDrag = true; }});
canvas.addEventListener("mouseup", function (evt) { if(imageDrag) imageDrag = false;});
setInterval(function() { if(imageDrag) { context.clearRect(0, 0, canvas.width, canvas.height); imageX = mouseX; imageY = mouseY; context.drawImage(upload_image, imageX, imageY); }}, 1000/30);
How to use multiple click event on a canvas
Letting the browser do (most of) the workOn click of the red part it should call function1 and on click of gray part, it should call function2.
You can use reusable path objects to store the different paths you want to test against and then use isPointInPath()
with path and coordinates as arguments.
By checking each path for a hit you can assign a different call based on for example index.
And there is no need to do this:
var c2 = document.getElementById("myCanvas");
var ctx2 = c2.getContext("2d");
This will simply reference the same context as a canvas can only have one - if requested more than once the same will be given (or null if different type).
How to use multiple click event on a canvas
You can share the click handler to do what you want as shown below -
For modern browsers you can use both Path2D objects to store path information you want to use later (I'll address older browsers in the second example).
Example
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
var p1 = new Path2D();
var p2 = new Path2D();
var paths = [p1, p2]; // store paths in array for check later
// store arc parts to respective path objects
p1.arc(100, 75, 50, -0.1 * Math.PI, 1.7 * Math.PI); // red part
p2.arc(100, 75, 50, 1.7 * Math.PI, -0.1 * Math.PI); // grey part
// render the two path objects using a common context, but different style
ctx.lineWidth = 15;
ctx.strokeStyle = "#c32020";
ctx.stroke(p1);
ctx.strokeStyle = "#a9a9a9";
ctx.stroke(p2);
// check for clicks on common canvas
c.onclick = function(e) {
var rect = this.getBoundingClientRect(), // adjust click coordinates
x = e.clientX - rect.left,
y = e.clientY - rect.top;
// iterate through path array to test each path for hits
for(var i = 0; i < paths.length; i++) {
if (ctx.isPointInStroke(paths[i], x, y)) { // check which path
console.log("Path " + (i+1) + " clicked");
break;
}
}
};
<canvas id="myCanvas"></canvas>
Onclick listener in canvas
Try this..
document.getElementById('canvasId').addEventListener('click',function(evt){
alert(evt.clientX + ',' + evt.clientY);
},false);
html5: how to handle canvas child clicked event?
The way to do this, is by handling the click event of the canvas, and then figure out yourself what part of the canvas is clicked:
canvas.addEventListener("mouseup", doMouseClick, false);
var doMouseClick = function(event)
{
//Some magic to have the exact coordinates in the canvas:
var clickPos = {
x : event.clientX + document.body.scrollLeft + document.documentElement.scrollLeft - Math.floor($(canvas).offset().left);,
y : event.clientY + document.body.scrollTop + document.documentElement.scrollTop - Math.floor($(canvas).offset().top) + 1
}
//check the image
if (clickPos.x > 128 && clickPos.y < 128 + imageObj.width
&& clickPos.y > 128 && clickPos.y < 128 + imageObj.height){
console.log("Oh boy! Someone clicked the image!");
}
}
The reason why we have to do it this way, is because the you don't "add" your image as a child to the canvas, you "draw" it on the canvas. The canvas just shows pixels and has no idea what is actually drawn.
How to add an onClick event handler to a canvas shape in Elm?
In Elm, using the Canvas rendering, you should use the Mouse.clicks
signal and react to changes in the signal. Here's a runnable example of how that would work:
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
In essence, Mouse.clicks
are the actual "events" we are interested in, so whenever one happens, we "sample" the Mouse.position
signal to get the click position.
Signal.sampleOn
produces a signal that updates with the value of the second parameter signal (here, the mouse position) whenever there is a change in the first parameter signal (here, the mouse clicks).
Now, just to get the result showing, we are also mapping the position to the show
function in main
.
You can also paste this code to http://elm-lang.org/try, compile and try clicking the right-hand side to see it working.
Related Topics
How to Sort Data in Ascending or Descending Order in Reactjs
Remove Everything After Last Backslash
Allow Only One Checked Checkbox, Angular Best Practice.
How to Hash Passwords Before Posting and Then Using Bcrypt
Reactnativejs: Referenceerror: Can't Find Variable: View
Running Functions One After Other in React
How to Make a Auto-Increment Id in My Table Td Using Jquery
Run Script After Appending It to the HTML
How to Synchronize the Scroll Position of Two Divs
Preventing Page from Scrolling on Focus Switching
Want to Show/Hide Div Based on Dropdown Box Selection
How to Write an Onclick Function for a Dynamically Generated Button
How to Mute Video With JavaScript or Jquery
Move an Image With JavaScript Using Mouse Events
Window.Scroll Smooth Not Working on Safari
Npm Warn Enoent Enoent: No Such File or Directory, Open 'C:\Users\Nuwanst\Package.Json'
How to Fetch Url of Current Tab in My Chrome Extension Using JavaScript