Basic Canvas with JavaScript

The Canvas APi gives you the ability to use JavaScript to draw inside a HTML element. JavaScript can draw lines, circles, or rectangles. Text can be added. Images and video can also be used to create a full Canvas.

Canvas is focused on 2d, for 3d WebGL API uses the Canvas.

As items are added to the canvas, each item will be placed in front of the other. Keep that in mind as you design the JavaScript. Start will the items in the back and work forward.

I’m going to keep this short and simple. The Canvas is very expanse. As I learn more I will come back and talk about animations and drawing paths.

HTML

The HTML portion of the Canvas API <canvas> is very simple. A single element. Nothing is required but a few things make it a little easier.

An id should be added to make using the element from JavaScript much easier. The width and height marks the size of the Canvas. Another optional part is adding some text inside the Canvas element just in case the user is using a browser that doesn’t support the Canvas tag.

<canvas id="myCanvas" width="600" height="400">
    Your browser doesn't support Canvas.
</canvas>

Truthfully you’ll find very few users that don’t support this. According to CanIUse.com Canvas is supported on 98.43% of all uses; as of 2019-04-07. Even IE supports Canvas starting back on IE 9.

The main reason that the Canvas element won’t work is because JavaScript is disabled. There are many reasons a user will have the JavaScript disabled. Lucky enough it’s very easy to fallback. Simple text with what would be displayed is the quickest but you could add HTML inside the canvas element and the browser will display that since JavaScript won’t be replacing it. For example, if you were displaying a stock chart, you could just put the stock information in a table. Or an image could be placed instead.

<canvas id="chart" width="150" height="150">
  <img src="images/chart.png" width="150" height="150" alt=""/>
</canvas>

It’s always a good idea to have some sort of fallback that lets users at least get some use if not all when visiting your site.

JavaScript

The entire reason for Canvas is to let JavaScript do some drawing.

Accessing the Canvas

The first step to put the Canvas into JavaScript variables. There are two parts that you’ll need to grab for almost all tasks.

The Canvas element itself is used to determine how large the Canvas is. Also it lets you access the Canvas Context. The context is what you will be drawing on.

const canvasElement = document.getElementById('myCanvas');
const canvasContext = canvas.getContext('2d');

Most instructions I’ve seen list the context as ctx. While this is nice and short, and you’ll like having it short considering how many times you’ll need to be writing it, I like having my variables very meaningful. So for this post, I’ll be using a longer variable name.

Coordinate system

The Canvas uses a (x, y) coordinate system. (0,0) is in the upper left hand corner. x is positive going to the right. y is positive going down. For example ( 10, 20) starts at the upper left hand corner and moves 10 to the right and 20 going down.

This can be changed using canvasContext.translate(x,y). We’ll demonstrate this later.

Drawing a rectangle

canvasContext.fillStyle = '#GG4499';
canvasContext.fillRect(10,10,50,50);

fillStyle sets the color that is being used. This can be any CSS type of color; ‘#333444’, ‘rgb(200,0,0);

fillRect(x, y, width, height) draws the rectangle. The x and y will the upper right hand corner of the rectangle.

Maybe you don’t want it filled in? Just an outline? What you would see is just the stroke not the fill. :)

canvasContext.strokeStyle = 'red';
canvasContext.strokeRect(x, y, width, height);

strokeStyle lets you pick the color of the rectangle same options as fillStyle.

Clearing a rectangle

canvasContext.clearRect(x,y, width, height);

The idea is the same as fillRect except it clears the pixels in the rectangle. This is useful when you are redrawing an image. If the image is moving you’ll want to clear the space first so that the old image is gone.

If you want to clear the entire canvas, use:

canvasContext.clearRect(0,0, canvasElement.width, canvasElement.height);

Drawing Text

canvasContext.font = '48px serif';
canvasContext.fillText(text, x, y);
canvasContext.strokeText(text, x, y);

Both of these are very similar. The difference is that strokeText will make an outline where fillText will fill it in.

canvasContext.font allows you to set the font size and font family before drawing the text on the canvas. Other options are:

canvasContext.textAlign = value; // options are start, end, left, right or center. Default is start.
canvasContext.textBaseline = value; // options are top, hanging, middle, alphabetic, ideographic, bottom. Default is alphabetic.
canvasContext.direction = value; // options are ltr, rtl, inherit. Default is inherit

Showing an image

We can load an image into the canvas along side all the other things we have going on.

const image = new Image();
image.onLoad = () => {
    canvasContext.drawImage(image, x, y, width, height);
};
image.src = 'https://placeimg.com/300/400/arch';

So what we are doing here is creating a image object. The image.onLoad will happen when the image has been loaded into memory. We are using a arrow function that will then add the image onto the canvas. The final step is to set the src of the image. That will cause the image to load.

Another option is to use an image that is already on the page. This is assuming there is an img element with the id of imageSource in the HTML that we will be coping.

const image = document.getElementById("imageSource");
canvasContext.drawImage(image, x, y, width, height);

Translate

Something that confused me at first was the translate option. Using translate lets you reset where the (0,0) is at. This makes it easier to work in a certain area of the canvas.

canvasContext.translate(10,10);

Here’s an example.

canvasContext.fillRect(10,10,40,40);
canvasContext.translate(10,10);
canvasContext.fillRect(0,0,20,20);

Just looking at the two fillRect you’ll think that they are at different locations but because of the translate the squares are at the same locations.

When using translate it’s best to save and restore before and after you make the changes.

canvasContext.save();                   // save the drawing state
canvasContext.translate(50,50);         // move the origin
canvasContext.fillRect(0,0,20,20);      // draw a rectangle
canvasContext.restore();                // restore the drawing state
canvasContext.fillRect(0,0,20,20);      // draw a rectable

Even though both of the fillRect have the same (x, y) the translate and restore are changing where that point is.

The save() and restore() will store more then the translate.

Codepen

Here is a pen that has these functions all set up and ready to go.

See the Pen Basic Canvas API by Russ Eby (@RussEby) on CodePen.

Resources

MDN Canvas API