Being able to draw shapes is cool and all, but we want to add interactivity to our graphics!
In this lesson, we will learn how to add 'click'
handlers to our canvas
elements using the addEventListener
method.
[00:01] To add click interactions to HTML canvas elements, I went ahead and started us off with a canvas that has a height and width of 200, and then gave us a display co-ords class div that is invisible, but it's down there, I promise.
[00:18] Inside of our JavaScript, I created a couple of variables. The canvas variable, to go ahead and grab that ID of canvas. The context variable, to get the 2D context of that canvas, and the co-ords variable, which is grabbing the div with a class of display co-ords for us, so that we can populate it with the co-ordinates once we have them.
[00:43] I'm also coloring our fill style the context of pink and drawing it as a rectangle with the same width and height of our canvas.
[00:53] To get started, let's call out our canvas and an event listener. That event listener will be on-click. I'm going to call the method getCo-ords. We now need to create that getCo-ords method.
[01:16] We'll say const getCo-ords is equal to. We're going to pass it the click event. We're all on board? Awesome. Now, inside of our getCo-ords function, we want to go ahead and create two variables.
[01:31] The first is going to be the x variable, and the second is going to be the y variable. With our click event, we should be able to say event.client, and then it has two things that you see here, x and y. We'll set constx=event.clientx, and consty=event.clienty.
[01:55] Now, for the final piece, to start seeing something on the screen, we're going to grab that co-ords variable that we create above. We'll say co-ords.textContent, and set that equal to -- now follow along closely, back tick, back tick. Inside here, we'll do a little string interpolation.
[02:19] We want to go ahead and pass it the x variable and the y variable that we just created. On screen, we should see number, comma, number. Save, refresh, click. Look at that gorgeousness.
[02:37] If I click on the top left, we might expect to get 00However, I'm getting closer to something like 10,120 when I'm over here. This is because the event.clientx and event.clienty are not grabbing co-ordinates relative to the square here. They're grabbing it relative to the entire page.
[02:59] At this point when I clicked, I was 12 pixels over from the left side of the screen, and I was 120 pixels down from the top side of the screen.
[03:08] If we're wanting to build a color picker, or for some reason, we want to print out cool numbers that are relative to the square we're clicking on, this would not work. We need actual co-ordinates to the square.
[03:21] The next step is going to be creating another variable in here. I like to call it container because that makes logical sense to me, but you can call it whatever you'd like. We'll say canvas.getBoundingclientrect. Boundingclientrect is going to give us access to some pretty cool stuff.
[03:40] Inside that constx variable that we just created, I'm going to subtract the event.clientx from the container.left, left side, and the y, as you may or may not have guessed, I'm going to subtract from the top, container.top.
[03:57] If we go back and refresh, click in the top right-ish area, see we're getting much closer to 00If I could actually click on 00you would see that. The bottom right, we are close to 200,200, which if you remember is the width and height of the canvas container, and also the fill rect right here, canvas width, height.
[04:19] We're achieving now co-ordinates that are based only off of this square that we're clicking in, which is wonderful. That's great.
[04:27] However, sometimes whenever you're building things like color pickers, you do need, whenever you click in the very center of this object, this element here, you need that to be 00and you need this to be 100,100, and this to be -100,-100 like an actual co-ordinate plane.
[04:45] The next step in achieving something like that is a little bit more math. We'll surround these guys with parenthesis. We're going to use container again. We're going to say subtract that constx that we just created from the container's width divided by 2.
[05:06] We're going to do the same thing for our y variable, but instead of width, we're going to do height. Go, refresh. Now, when I click in the center-ish area, we should get close to 00right, close to 100,100. Then over here, -100,-100.
[05:25] Of course, as any good co-ordinate plane does, if you're in the top, it's a positive number followed by a negative number. If you are on the bottom left, it's a negative number followed by a positive number.
[05:37] Voila. Don't you just love the math?
Why does Y have .125 but X is an integer.
Yes, I was wondering as well why does the Y value contains fraction digits if we are only subtracting integer values for the coords?
@Stephen James & @Pascal Chouinard: I suspect, in this case, canvas.getBoundingClientRect() top and bottom are not integers. That is, while the Bounding Client Rect reports alignment to integers on the x axis, it does not report alignment to integers on the y axis.
Likely if you remove the <H1> above the canvas, you would see integer alignment from the events.
<!-- <h1>Add click interaction to HTML Canvas</h1> -->The replies above included the notion of removing the H1 line to see integer alignment of the canvas. But the back-end filtered it out.
Sorry, I can't get edit to work in this thread.
aaah ok, thanks @Ray
// if you want top right to be: positive, positive, and. . .
// you want bottom left to be: negative, negative. . .
const x = (event.clientX - container.left) - container.width/2;
const y = container.height/2 - (event.clientY - container.top);