Jordan Savant # Software Engineer

Javascript Canvas

An HTML element which can be used to draw graphics using scripting.

Setting Up

The html element is simple enough.

<canvas id="canvas" width="640" height="480"></canvas>

Then we can find our canvas element and create a 2D or 3D context for us to work with.

var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');

Common Methods

// Styling
ctx.fillStyle = 'rgb(200, 0, 0)'; // set the color of the fill command
ctx.strokeStyle = 'rgb(200, 0, 0)'; // set the stoke style

// Rectangles
ctx.fillRect(25, 25, 100, 100); // create a rectangle with the fill style
ctx.clearRect(45, 45, 60, 60);  // creates a transparent rectangle, erases
ctx.strokeRect(50, 50, 50, 50); // creates a rectangle with only a stroke outline

// Paths
ctx.beginPath();      // creates a new path
ctx.moveTo(75, 50);   // moves coordinates of what we are about to draw
ctx.lineTo(100, 75);  // creates a path line
ctx.lineTo(100, 25);
ctx.fill();           // fills in the path, (triangle example)

ctx.beginPath();      // similar example will stroke a triangl
ctx.moveTo(125, 125);
ctx.lineTo(125, 45);
ctx.lineTo(45, 125);
ctx.closePath();
ctx.stroke();

// Circles
arc(x, y, radius, startAngle, endAngle, anticlockwise); // arc at x,y from and to angle, finally direction (default clockwise)
arcTo(x1, y1, x2, y2, radius) // draws an arc connected with a line to previous point

Basic Animation

These are the steps you need to take to draw a frame:

  1. Clear the canvas
  2. Save the canvas state
  3. Draw animated shapes
  4. Restore canvas state

We can set intervals for drawing with the following Javascript functions:

  • setInterval(func, delay) - raw draw loop
  • setTimeout(func, delay) - useful for listening to input commands
  • requestAnimationFrame(callback) - runs at 60fps

Here is a basic structure of how we could run a draw loop with a bouncing rectangle

<canvas id="canvas" width="600" height="400" style="border: 1px solid gray;"></canvas>
function init() {
    window.requestAnimationFrame(draw);
}

var speed = 3; // px per frame
var x = 10; // starting pos
function draw() {
    var ctx = document.getElementById('canvas').getContext('2d');
    var canW = document.getElementById('canvas').scrollWidth;
    var canH = document.getElementById('canvas').scrollHeight;
    ctx.globalCompositeOperation = 'destination-over'; // draw our new stuff behind old stuff (so we dont jitter)
    ctx.clearRect(0, 0, canW, canH); // clear canvas

    ctx.fillStyle = 'rgba(10, 10, 10, 0.4)';
    ctx.strokeStyle = 'rgba(0, 153, 255, 0.4)';
    ctx.save();

    ctx.fillStyle = 'rgb(200, 0, 0)';
    ctx.fillRect(x, 10, 50, 50);
    x += speed;

    var xMin = 10;
    var xMax = canW - 50 - 10;
    if (x > xMax) {
        speed = -3;
    } else if (x < xMin) {
        speed = 3;
    }

    window.requestAnimationFrame(draw); // recursive draw
}

init(draw);