Draw with Your Mouse on an HTML Canvas

John Lindquist
InstructorJohn Lindquist

Share this video with your friends

Send Tweet
Published 3 years ago
Updated a year ago

The canvas element exposes a 2d context which allows you to draw lines using the moveTo, lineTo, and stroke api. You can combine this with Mouse events to make a simple drawing app.

Instructor: [0:00] Let's start by creating a canvas with document-create-element-canvas, and we'll name this canvas. With that created, we can append it to the body-with-body-append-child-canvas.

[0:14] Then to be able to draw, we need to get the context off of the canvas. The 2-D context is the one we use for the drawing API. We'll name this context.

[0:27] To test if this is working, we can move to - to say where to start and then line through 100-100. That's where it'll draw a two. Context-stroke does the actual drawing. If I save here and refresh, you can see a line going from - to 100-100.

[0:48] First, we need to get rid of this margin here because the document body's margin does not default to zero, so let's go ahead and do that. Document-body-style-margin is zero. Now we refresh and that tucked that up in the corner.

[1:03] Then you'll notice if we try and draw it to the bottom of the screen -- I'll make the y-coordinate 1,000 and hit refresh -- it gets cut off right here rather drawing all the way to the bottom.

[1:14] To fix that we can say canvas-with is the same as the document-body-client-width, and then the same thing with height. We can client-height and canvas-height. Hit save there and refresh. Now it's going all the way to the bottom.

[1:32] To start our drawing, we'll do a canvas-add-event-listener and listen for mouse-move. We'll define a callback here where the event has the x- and y-coordinates to draw to, so we'll get those. They're called page-x and page-y. Grab those off the event. Page-x and page-y are essentially the x and y based on that top-left corner of the page.

[1:55] I'm going to rename those to x and y to save myself some typing. Then I'll grab these, cut and paste here. I'll say line to x and line to y, hit save, refresh. When I move my mouse, you can see it's drawing from - to wherever my mouse is.

[2:17] Instead of drawing from -, we're going to set up a previous point, or previous coordinate. I'll just name it previous. I'll say this is x- and y-. We'll say we move this to previous-x and previous-y.

[2:35] Then to start with, we're going to canvas-add-event-listener mouse-down, get the event here. We'll use the same page-x and page-y from here, paste it there, and say that previous is now x and y in this event.

[2:53] Now when we try this, we'll refresh. It's drawing from -. I click, now it's drawing from that point. I click, it's drawing from that point, click, and drawing from that point.

[3:04] Now while this looks really cool, what we actually want is previous to update every time the mouse moves. We'll say previous is x-y at the end of this block, so after it uses it, it will assign it to this new x and y. We'll hit save here and refresh. You can see as I move my mouse, it starts drawing.

[3:28] Finally, we want this to only draw if the mouse is down. I'll start with is-mouse-down and start that as false. When I click on mouse-down, I'll say is-mouse-down-is-true and then we'll create another event listener for mouse-up. We'll eat some of this and set is-mouse-down to false.

[3:54] Then I can wrap this entire block here inside of an if-statement, which checks if-is-mouse-down. We'll make our block, cut and paste that in there.

[4:07] Now when I refresh, I'll click the mouse, it'll start drawing. I hold the mouse down, I'll release the mouse, move the mouse around, click, start drawing, release, move the mouse around.

[4:19] Right now, the path here is a little jaggy and that has to do with our drawing path using a subpath based on move-to. Instead we can start a new path each time and to say context-begin-path. That will clear up our drawing a little bit.

[4:34] If I refresh, start drawing, you can see the path is a bit smoother now because each time I move the mouse, it's creating a new path. Then if you were to make the context line width something like 10, and I try drawing with something really thick, you can see there's some spaces in between, which is kind of a cool effect.

[4:57] If you want to remove that white space, you can change what's called the line-cap -- of-context-line-cap -- and set that to round. Each line will have rounded corners, which will fill in that gap between your drawing paths.