Login | Register   
LinkedIn
Google+
Twitter
RSS Feed
Download our iPhone app
TODAY'S HEADLINES  |   ARTICLE ARCHIVE  |   FORUMS  |   TIP BANK
Browse DevX
Sign up for e-mail newsletters from DevX


advertisement
 

Introduction to the HTML5 Canvas

Gigi Sayfan demonstrates some of the capabilities of the HTML5 canvas along with integration with other HTML elements.


advertisement

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.

Setup

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

<!DOCTYPE html>
<html>
<div>
<button id="button" onclick="onButtonClick()">Run</button>
</div>
<canvas id="main_canvas">
Your browser does not support the HTML 5 Canvas element.
</canvas>

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 1000x1000 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;
}

Interaction

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];
}

Conclusion

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.



   
Gigi Sayfan is the chief platform architect of VRVIU, a start-up developing cutting-edge hardware + software technology in the virtual reality space. Gigi has been developing software professionally for 21 years in domains as diverse as instant messaging, morphing, chip fabrication process control, embedded multi-media application for game consoles, brain-inspired machine learning, custom browser development, web services for 3D distributed game platform, IoT/sensors and most recently virtual reality. He has written production code every day in many programming languages such as C, C++, C#, Python, Java, Delphi, Javascript and even Cobol and PowerBuilder for operating systems such as Windows (3.11 through 7), Linux, Mac OSX, Lynx (embedded) and Sony Playstation. His technical expertise includes databases, low-level networking, distributed systems, unorthodox user interfaces and general software development life cycle.
Comment and Contribute

 

 

 

 

 


(Maximum characters: 1200). You have 1200 characters left.

 

 

Sitemap
Thanks for your registration, follow us on our social networks to keep up-to-date