Spicy Yoghurt | Last updated: 9 March 2019 | HTML5 game

Draw on the HTML5 canvas

Learn how to set-up a HTML5 file and draw on the HTML5 canvas. You'll learn about the canvas, how to get a reference and how to perform drawing operations. By the end of this tutorial you can create your own canvas graphics.

What is a HTML5 canvas?

When you want to draw your own image, animation or game with HTML5, you'll need a canvas. The <canvas> tag is new in HTML5. It's a container for graphics and you can draw on it by using JavaScript. You can draw paths and shapes, but also text and images.

It works like an <img> tag, only you can draw the image yourself instead of loading it from an external source. In fact, in modern browsers, you can even right click a canvas element and save the image. It's like a dynamic image.

The canvas will be the core of all the drawing operations for your game. It works like a drawing board. You can draw on it and clear it. Do it quickly enough and you will get the perception of motion. This is the basic principle of animations and games.

In this tutorial you'll learn about drawing a static image to the canvas. Check out the canvas animation tutorial if you already know how to do that and want to draw dynamically straight away.

Set-up a basic HTML5 file

Before you can draw any kind of graphics, you'll have to set-up a basic HTML5 file. You'll have to tell the browser how to interpret the file and what kind of content it contains. Let's get started with the code below:

                        <!DOCTYPE html>
                        <html lang="en">
                                <meta charset="UTF-8">

                                <title>HTML5 Game</title>
                                <meta name="description" content="A basic HTML5 game">
                                <meta name="author" content="[Your name]">
                                <!--Your canvas will come here -->

                                    //Your script will come here
Let's take a closer look:
  • The <!DOCTYPE> declaration tells the browsers what HTML version the page is written in. The HTML5 doctype is short and simple compared to older versions.
  • The <meta> tags and the <title> tag describe the content of the page. Search engines like Google use this information to build search results.
  • Inside the <body> tag is where all the actual content of the page will be stored. This is also where your canvas will be placed.
  • You can see two <script> tags right before the end of the <body> tags. Between those tags is where your program is going to start.
You can copy this code and store it in a file named index.html. This file can be run by any browser and will display your newly created HTML5 web page. Too bad it is still completely empty. Let's do something about that by adding a canvas.

Add a HTML5 canvas

Now directly after the <body> tags, add a <canvas> element. This is the place where the graphics of your game will be drawn later on.

                <canvas id="canvas" width="750" height="400" style="border:1px solid lightgrey;">
                    Your browser does not support the HTML5 canvas tag.
When you try to show the canvas in a browser that has no canvas support, the fallback content will be shown. For now, it's just a simple message about lacking support, but you could make something fancier and place it between the <canvas> tags.

Scaling the canvas to fit on all screen sizes

When you refresh your page, you should see the border of the canvas. The element has its width and height properties set. That's to define the size of your canvas, your drawing board. Every drawing operation will be performed in this coordinate space.

You can scale the total canvas by using standard CSS to set a width and height percentage on the element. For example, applying width: 100% to the element would stretch the canvas to fit the maximum width. But all drawing operations will still be done within the coordinate space of the canvas. You'll never have to take the actual size of your canvas into account when drawing.

How is this helpful? Well, this enables you to work on a game with a set resolution, let's say 1280x768, and run this game on devices with bigger and smaller screens. While programming, an x-position of 1280 will always be the right edge of your screen even if the actual screen size of the current device is much smaller or larger than that. The scaling of the canvas takes care of that.

Nothing is drawn on the canvas yet. You need to get a reference with some JavaScript code to do that.

Get a reference to the canvas

To perform drawing operations, you'll need a decent reference in your code to your canvas. Expand the <script> tags with the following JavaScript code:

                            "use strict";

                            // Declare as variable
                            var canvas;
                            var context;
                            // Listen to the onLoad event
                            window.onload = init;

                            // Trigger init function when the page has loaded
                            function init(){
                                canvas = document.getElementById('canvas');
                                context = canvas.getContext('2d');

                                // Draw something!
The most important steps are taken inside the init() function. In there the canvas is stored for later reference by calling getElementById() to retrieve the canvas element.

The canvas has no functions to draw on its own, you'll need a context for that. Call getContext() to retrieve the context from the canvas. '2d' is passed as argument to get a CanvasRenderingContext2D object. That's the context you need to draw 2D objects. There are also other context types like WebGL, for 3D, but that's not what we need right now.

Once the references are made, the first drawing operation is performed by calling draw().

The window.onload event will trigger once the whole page is loaded. This will make sure all elements and resources on the page are available before you execute your code. The init() function is set as the event handler. Once the onload event fires, init() will be called and the canvas will be available for referencing.

"use strict" is telling the browser to run the code in strict mode. This means your code will be validated more strictly. Things like using an undeclared variable are no longer allowed. This will force you to write cleaner code, which will prevent coding errors. It is an optional line, but it is recommended to leave it in. Learn more about use strict here.

Draw on the canvas

The last piece of the puzzle is the draw() function. The function looks like this:

                    function draw(){
                        // Get a random color, red or blue
                        context.fillStyle = Math.random() > 0.5? '#ff8080' : '#0099b0';

                        // Draw a rectangle on the canvas
                        context.fillRect(100, 50, 200, 175);
At first, a color is selected as fill style for the context by setting fillStyle. Then, the actual drawing operation is performed to draw a rectangle to the canvas, by calling fillRect(). The position and size of the rectangle are passed as arguments.

This is how most canvas operations work. You define a style and then fill. You could say you first define the brush you want to use and then start to paint. Also, notice how the paint color isn't passed into the fill function. It is stored in the context. This means that every next drawing operation will use the same paint as the current. Until you change the fill style of course.

When you add the previous code to your index.html file, and run the file in the browser, you will actually see something getting draw on the canvas. It's a big rectangle! With the current code, the rectangle is either red or blue. This is because every time the page is loaded a new random color is picked in the draw() function, by using Math.random() to pick a color as fill style. You can try to refresh this page a couple of times and see the color getting changed.

The random color is used to demonstrate the fact that you are not looking at a static image. You are drawing your own graphics! You can modify the arguments inside the function to create rectangles of different sizes and colors.

Draw shapes with paths

The 2d-context only supports one primitive shape, and that's the rectangle. You could use this to draw a square, by making a rectangle with even sides. But if you want to draw anything else, like a triangle, circle or any other shape, you'll have to use a path.

Paths start by calling beginPath() on the context. You then define the shape of your path. This can be a circle or a line for example. After defining the path you can call fill() to draw the path. This tutorial won't dive deep into paths but here are some quick examples to get the idea.

How to draw a circle?

Here's a piece of example code that draws a circle. You can see it starts with the beginPath() function and ends with fill().

                    context.arc(200, 100, 50, 0, 2 * Math.PI);
The arc() function is the one who defines an arc-shaped path, in this case a full circle.
  • The first two arguments are the x and y of the center of the circle.
  • The third is the radius of the circle. A larger radius will make for a larger circle.
  • The last two arguments are the starting angle and ending angle of the arc in radians. This example circle starts at an angle of zero and ends at an angle of two times pie, making a perfect circle.
You can stack up multiple commands, like arc(), to create more complex shapes.

How to draw a triangle?

By using multiple commands, you can draw up more complex shapes. This enables you to create a triangle existing of three lines. Here's an example on how to draw a triangle:

                    context.moveTo(200, 100);
                    context.lineTo(250, 150);
                    context.lineTo(250, 50);
Again it starts with calling beginPath(). The next call, moveTo(), is telling the context where to start drawing the path. So, it doesn't really draw anything on its own, it only tells on which coordinates to start. From there you can draw lines with lineTo() to create the desired shape.

Notice how lineTo() is called only twice. But you needed three lines for a triangle, right? The last line is automatically drawn when you call fill(). It closes the path and connects start to end.

Stroke the outlines of a path

You have been using fillRect() or fill() to draw on the canvas. But there is another option. Instead of filling, you can also stroke paths. Here is an example of previously used shapes that are stroked and not filled.

                        context.arc(200, 100, 50, 0, 2 * Math.PI);
                        context.strokeStyle = '#0099b0';

                        context.moveTo(200, 100);
                        context.lineTo(250, 150);
                        context.lineTo(250, 50);

                        context.strokeStyle = '#ff8080';
                        context.strokeRect(100, 50, 100, 125);
As you can see fill() and fillRect() have their counterparts stroke() and strokeRect(). There even is a strokeStyle attribute just like fillStyle.

In the example, the circle is drawn in blue, then the triangle is drawn without specifying a specific color, and then the rectangle is drawn in red. Since the context stores the fill- and stroke style, the triangle is drawn in blue too, without specifying this specifically.

And there is another notable thing happening here. The triangle is not so much a real triangle. It is more like a rotated L-shape. That's because, unlike the fill() command, stroke() doesn't tie the begin of the path to the end. If you need a stroke of a triangle, you'll have to specify three lines, not two.

That's all for now on paths. If you like, you can experiment with different shapes and drawing operation to create graphics of your own. For this tutorial, you'll be using fillRect() for the time being and switch to images later on.

Final code

You finished this tutorial and have your own HTML5 canvas ready to use. You can perform your own drawing operations now. You can download the final code here. Feel free to ask questions in the comments.

Of course, this is only just the start. In the next step of the tutorial, you will learn how to do multiple drawing operations in a row. You will create a game loop!

Leave a comment