#Basics

Basic Usage

When using canvas, first place a canvas into the document as an element.

<canvas width="400" height="400" id="canvas"></canvas>

The width and height attributes will control the size of the canvas. These attributes control the size of the drawing canvas, not the actual rendered size. See the "Canvas Dimensions" page for more.

In order to use a canvas, we must first grab the element from the page as a DOM element, and then get a drawing context from it.

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

All drawing calls after this will be made from the ctx object. The ctx represents the drawing context of the object, and contains information about the 2D drawing space. The canvas object is the actual DOM element. Interacting with it allows us to access attributes like width and height.

There are a few available drawing contexts, including webgl. WebGL is really an entirely different technology, so we will only focus on 2D drawing.

Canvas Dimensions

The width and height attributes will control the size of the canvas. These attributes control the size of the drawing canvas, not the actual rendered size.

See the Pen Canvas dimensions demo by Alan Luo (@alanluo) on CodePen.

In the above pen, both canvas elements have the same dimensions set through CSS. However, one has twice the height set through the height attribute, thus leading the exact same rectangle to become rendered at half the height.

This can cause problems when you want to make a dynamically sized canvas. For instnace, you may want to make a full-screen canvas, or use a canvas as a thumbnail.

In order to make the size of the drawing context match the rendered size of the canvas element, we have to force this in realtime. One common practice is to put the following handler in the onResize listener.

// somewhere early in the script
var canvas = document.getElementById("canvas");
...

window.addEventListener("resize", function() {
    canvas.setAttribute("width", canvas.scrollWidth);
    canvas.setAttribute("height", canvas.scrollHeight);
    console.log(canvas.offsetWidth);
});

Paths in Canvas

Paths are the building block of drawing in Canvas. A path is just a shape. Then, the shape can be drawn on by either stroking it or filling it.

We can create use paths with beginPath, fill, and stroke.

ctx.beginPath();
ctx.rect(0, 0, 100, 100);
ctx.fillStyle="black";
ctx.fill();

This creates a black square in the upper-right corner of the canvas. We can change strokes and fills with strokeStyle and fillStyle, which both take CSS-like color strings. We can also use lineWidth to make strokes thicker.

ctx.beginPath();
ctx.moveTo(0,0);
ctx.lineTo(300,150);
ctx.moveTo(0, 100);
ctx.lineTo(300, 250);

ctx.strokeStyle="red";
ctx.lineWidth=2;
ctx.stroke();

There are four basic drawing functions: rect, moveTo, lineTo, and arc.

Note that these functions add to the working path. They don't create new paths.

//example 1
ctx.beginPath();
ctx.rect(0, 0, 50, 50);
ctx.rect(100, 100, 50, 50);
ctx.fill();

//example 2
ctx.beginPath();
ctx.rect(0, 0, 50, 50);
ctx.beginPath();
ctx.rect(100, 100, 50, 50);
ctx.fill();

The first example will draw two squares, while the second will only draw one since beginPath discarded the first rectangle on the old working path.

This fact leads to a common mistake in making canvas animations.

var x = 0;
var y = 0;
function draw() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);

  ctx.rect(x, y, 50, 50);
  ctx.fill();
  x+=1;

  window.requestAnimationFrame(draw);
}

window.requestAnimationFrame(draw);

The above animation, which is supposed to make a square move across the screen, instead creates a long black bar. The reason is that beginPath is not called inside the draw loop.

Animation

To animate things in canvas, use window.requestAnimationFrame to set up a draw loop.

function draw() {
  /* code goes here */
  window.requestAnimationFrame(draw);
}
window.requestAnimationFrame(draw);

The below code will cause the draw function to be run every frame.

canvas has no special functions that allow for animating. You just have to be used to writing in animation loops. The usual design paradigm for animation loops is to update the state, then draw the state. For instance, to draw a square moving across the screen:

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

var x=0;
var y=50;
function draw() {
  // reset canvas
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  //update state
  x+=1;

  // render state
  ctx.beginPath();
  ctx.rect(x, y, 50, 50);
  ctx.fill();

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