Introduction to the HTML5 Canvas

One of the most exciting features of the HTML5 standard is the canvas tag. The canvas allows arbitrary 2D rendering of shapes and images as well as interactions via standard events. This can be used for interactive presentations, graphs, dashboards, simulations and, of course, games. The canvas has an API that is pretty low-level and includes various functions.

In this article, I’ll demonstrate some of the capabilities of the HTML5 canvas and integration with other HTML elements by implementing Conway’s game of life. This is a visualization of a very entertaining cellular automata that can generate very surprising patterns from super-simple ground rules. You can find the full source code here.

This is what it looks like:

If you click the button while it’s running the simulation stops and you can toggle individual cells by clicking them and then continue running by clicking the button again.


First, we need a basic HTML page to host our canvas:

Your browser does not support the HTML 5 Canvas element.

There is also a button there to alternate between two modes: Run mode — where the simulation is running and Edit mode — where you can edit the field.

In the beginning of the script tag we get the various objects from the DOM with which we will interact — the canvas itself, the graphics context and of course the button:

canvas = document.getElementById("main_canvas");context = canvas.getContext("2d");button = document.getElementById("button");

Then the canvas is properly sized and a few variables that will determine the look and feel are initialized:

canvas_size = 1000;canvas.width = canvas_size;canvas.height = canvas_size;size = 100;square = 10;running = false; 

The ‘running’ variable controls the mode. When, it’s ‘false’ we’re in editing mode

Finally, we get the board, which is a 2d array 1000×1000 initialized to zeros

board = get_board();function get_board() {    // Create 2d array    board = new Array(size);    for (var i = 0; i < size; ++i) {        board[i] = new Array(size);        for (var j = 0; j < size; ++j) {            board[i][j] = 0;        }    }    return board;} 

The window.onload() Function

In the browser, the primary place to hook up your JavaScript is the window.onload() callback function. The browser uses this function when the page has finished loading and all the HTML elements are accessible through the DOM.

window.onload = function() {    canvas.addEventListener("mousedown", onMouseDown, false);    main();    setInterval("main()", 30);};

Here, the onload() function is very simple. It sets up the onMouseDown() function to respond to mouse down events, then calls the main() function and sets a timer to repeatedly call it every 30 milliseconds, which is about 33 frames per second.

Main Loop

The main loop's logic is simple too. Clear the canvas, draw the current state of the board by displaying a rectangle with the right color in each cell position. Finally, if we're in the "running" state update the board by calling the update() function that does the heavy lifting and returns an updated board.

function main() {    context.clearRect ( 0 , 0 , canvas.width , canvas.height );    for (var i = 0; i < size; ++i) {        for (var j = 0; j < size; ++j) {            context.fillStyle = board[i][j] == 1 ? "black" : "magenta";            context.fillRect(i * square, j * square, square - 1, square - 1);        }    }    if (running)        board = update();}

Updating State

The update function implements the rules of Conway's game of life. Every live cell stays alive if, and only if, it has 2 or 3 live neighbors. Every dead cell comes alive if, and only if, it has exactly 3 live neighbors. First a new board is created and then the state of each cell is determined by counting its neighbors using the get_neighbors() function

function update() {    var new_board = new Array(size);    for (var i = 0; i < size; ++i) {        new_board[i] = new Array(size);        for (var j = 0; j < size; ++j) {            var value = board[i][j];            new_board[i][j] = value;            var neighbors = get_neighbors(i, j);            if (value == 1) {                if (neighbors < 2 || neighbors > 3)                    new_board[i][j] = 0;            } else {                if (neighbors == 3)                    new_board[i][j] = 1;            }        }    }    return new_board;}

The get_neighbors() function checks all the neighbors around a cell. Note, that cells on the edge have fewer neighbors and this is taken into account.

function get_neighbors(x, y) {    var count = 0;    for (var i = -1; i < 2; ++i) {        for (var j = -1; j < 2; ++j) {            var nx = x + i;            var ny = y + j;            if (i == 0 && j == 0)                continue;            if (nx < 0 || nx >= size)                continue;            if (ny < 0 || ny >= size)                continue;            count += board[nx][ny];        }    }    return count;}


There are two types of interaction that are very typical: clicking on a user interface element such as a button and clicking on the canvas itself and causing some effect. The button is used to switch the program's mode between "Running" and "Editing". Here is the code that just toggles the "running" variable and changes the text of the button:

function onButtonClick() {   running = ~running;   button.innerText = button.innerText == 'Run' ? 'Stop' : 'Run';}

When you are in editing mode and you click with the mouse on a cell, it toggles the cell  — a live cell becomes dead and a dead cell becomes live:

function onMouseDown(e) {    if (running)        return;    var x = Math.floor(e.offsetX / square);    var y = Math.floor(e.offsetY / square);    toggle(x, y);}function toggle(x, y) {    board[x][y] = 1 - board[x][y];}


The HTML 5 Canvas is a versatile new element that provides the power to create stunning interactive visualizations in a cross-browser manner. It can add a lot to the user experience when used properly. Developers can get a handle on it quickly, as it uses the familiar web platform of HTML/CSS/JavaScript.

Share the Post:
Share on facebook
Share on twitter
Share on linkedin

Related Posts