HTML <canvas>

Ben Garlock
5 min readJan 9, 2021

I’ve been toying around with JavaScript artwork and been having a lot of fun creating divs via loops and restyling them, rotating them, and making them move position across a DOM.

The only problem is that these projects are burning up my CPU. Creating a thousand divs and then randomly re-processing them… well it’s not very efficient. The fan in my computer often fires up after a few seconds of running one of these beasts.

Enter HTML <canvas>

I stumbled on this tool randomly while researching solutions to my little performance problem. Canvas is specifically design for high-volume DOM manipulation and does a much better job a creating flashy graphics and stunning landing pages.

Creating a canvas project

An actual canvas project begins with the <canvas> tag. You can insert this into a html file as you would any other tag.

<div id="root">
<canvas id="first-canvas">
</canvas>
</div>

No, you don’t use CSS.

Everything, and I mean everything, in a canvas project is created and styled by JavaScript. It’s part of what makes it so efficient. Using CSS to style a canvas object can actually work against you since CSS executes after the canvas has been rendered. This can cause warping and focus issues. Forget the fact that you won’t even have access to most of the objects inside a canvas, so no touchy css.

It’s kind of its own language.

(groan) I know. The canvas reference library is large, but getting familiar with it opens up a lot of opportunities. .beginPath() .moveTo(), not to mention the styling syntax can take some getting used to.

Let’s create a paint program.

In this exercise, we’ll create a small painting program where you can use your mouse to draw on a DOM. To start, we’ll need the following:

  1. index.html
  2. index.js
  3. index.css (to style a few things in our HTML doc)

index.html

<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="index.css" >
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>


<div id="root">
<canvas id="first-canvas">
</canvas>
</div>

<script src="index.js"></script>
</body>
</html>

index.css

* {
margin: 0;
padding: 0;

}

#root {
width: 100vw;
height: 100vh;
}

index.js

window.addEventListener("load", () => {


window.addEventListener('resize', () => {
canvas.height = window.innerHeight
canvas.width = window.innerWidth
})
})

Getting started

All of our work will be done in JavaScript. A few things to note: Our HTML doc contains a <canvas> tag, so we’ll need to pull this into our JavaScript file.

const canvas = document.querySelector("#first-canvas")

Getting the .context()

We now need to tell the system in which context we’ll be working with canvas. We are creating a two dimensional canvas, so we’ll specify that with a variable. To save typing, we’ll use ‘c’:

const c = canvas.getContext('2d')

We now have ‘c’ which is a 2d canvas object that we can start adding things to. ‘c’ is kind of like a min-DOM that we can adding items to. This is where the canvas reference library comes into play.

Styling

We need to make our canvas big. In this case we’ll make it take up the entire page.

canvas.height = window.innerHeight
canvas.width = window.innerWidth
canvas.style.backgroundColor = "light-blue"

Let’s style the line that we’ll be drawing

c.strokeStyle = "red"
c.lineWidth = '3'

Stying needs to be done BEFORE we start creating objects. It takes some getting used to.

Setting the environment

We need to tell the DOM what state our canvas is in when it first loads. Since we only want to start painting when our user clicks the mouse, we need to create a variable called “painting” and set it to false.

let painting = false

We also need to listen to our user actions that will call our painting functions when needed.

canvas.addEventListener("mousedown", startPosition)
canvas.addEventListener("mouseup", finishedPosition)
canvas.addEventListener("mousemove", draw)

Don’t worry, startPosition, finishPosition, and draw haven’t been created yet. We’ll do that now.

Get the starting position

In startPosition() we want to pass in our event, change our painting status, and call our draw function.

function startPosition(e) {
painting = true
draw(e)
}

Finish painting

Once a user stops holding their mouse down, we want to do the opposite of what we did in startPosition(), which is to set ‘painting’ to false and terminate our line. Using c.beginPath() effectively ‘chops’ off the line we’re drawing. If we didn’t do this, the line would continue the next time the user clicks.

function finishedPosition() {
painting = false
c.beginPath()
}

Drawing

Lastly, we need to create our draw function which actually creates our line. First though, we need to check our painting status to make sure it’s set to true.

if(!painting) return

Then we set our line parameters.

c.lineWidth = 10
c.lineCap = 'round'

Now we need to tell canvas the starting point of our line, then to draw the line, and finally where to end the line.

c.lineTo(e.clientX, e.clientY)
c.stroke()
c.beginPath()
c.moveTo(e.clientX, e.clientY)

The entire function looks like this:

function draw(e) {
if(!painting) return

c.lineWidth = 10
c.lineCap = 'round'

c.lineTo(e.clientX, e.clientY)
c.stroke()
c.beginPath()
c.moveTo(e.clientX, e.clientY)
}

And here is the index.js file in it’s entirety:

window.addEventListener("load", () => {

const canvas = document.querySelector("#first-canvas")
const c = canvas.getContext('2d')

//eventlistners
canvas.addEventListener("mousedown", startPosition)
canvas.addEventListener("mouseup", finishedPosition)
canvas.addEventListener("mousemove", draw)

//resize
canvas.height = window.innerHeight
canvas.width = window.innerWidth
canvas.style.backgroundColor = "light-blue"

c.strokeStyle = "red"
c.lineWidth = '3'

//variables
let painting = false

function startPosition(e) {
painting = true
draw(e)
}

function finishedPosition() {
painting = false
c.beginPath()
}

function draw(e) {
if(!painting) return

c.lineWidth = 10
c.lineCap = 'round'

c.lineTo(e.clientX, e.clientY)
c.stroke()
c.beginPath()
c.moveTo(e.clientX, e.clientY)
}

window.addEventListener('resize', () => {
canvas.height = window.innerHeight
canvas.width = window.innerWidth
})

})

That’s a quick crash course on canvas!

--

--