Canvas Element

Resources

The HTML Canvas Deep Dive book has been released as open-source. You can find the source on GitHub.

Adobe Illustrator to Canvas extension.

Concepts

Immediate Mode drawing vs. Buffered (Path Drawing) Mode drawing

Some drawing functions are executed immediately (strokeRect(), fillRect(), ), while others are buffered (lineTo(), rect(), ) and drawn later using a function such as fill() or stroke().

ctx.beginPath(); //Clears out the buffer
for(var i=0; i < 1000; i++) {
	var x = Math.random() * w;
	var y = Math.random() * h;
	var width = Math.random() * w;
	var height = Math.random() * h;
	ctx.rect(x, y, width, height); // store 1000 rectangles in path/buffer
}
ctx.stroke(); // draws the whole buffer at once

Buffering is quicker because the shapes are stored in the graphics processor and it allows for parallel processing.

Canvas Size

Resizing a canvas can be tricky if we don't know a few rules that might not be easily guessed:

  1. Changing the width or height property of a canvas in JavaScript erases its content and resets its context,
  2. Using percentages (%) in the CSS width and height properties of a canvas does not change its number of pixels/resolution. Instead, it scales the existing pixels without erasing the content, giving a blurry effect when a canvas becomes larger for example.

This is a handy way to do the sizing:

addListeners();
 		
// Event handling
function addListeners() {
	window.addEventListener('scroll', scrollCheck);
	window.addEventListener('resize', resize);
}
 	
function scrollCheck() {
	if(window.pageYOffset > canvas.height) {
		//Stop animation if it has scrolled off the screen.
		animateHeader = false;
	} else {
		if (!animateHeader) {
			//Kick-off the tweenLeg and animate loops if they are not running.
			for(var i in bees) {
				tweenLeg(bees[i]);
			}
			animateHeader = true;
			animate();
		}
	}
}

function resizeCanvas() {
	//Size canvas to entire viewport.
	canvas.width = getViewport().width;
	canvas.height = getViewport().height;
}

Utility Functions

Line Drawing

function drawLine(x1, y1, x2, y2, color, width) {
	ctx.save();
	// set color and lineWidth, if these parameters
	// are not defined, do nothing (default values)
	if(color)
		ctx.strokeStyle = color;
	if(width)
		ctx.lineWidth = width;
	// start a new path
	ctx.beginPath();
	ctx.moveTo(x1, y1);
	ctx.lineTo(x2, y2);
	ctx.stroke();
	ctx.restore();
}

Rounded Rectangle

function drawRoundedRect(ctx,x,y,width,height,radius,fill,stroke) {
	ctx.save();
	ctx.beginPath();
	// draw top and top right corner
	ctx.moveTo(x+radius,y);
	ctx.arcTo(x+width,y,x+width,y+radius,radius);
	// draw right side and bottom right corner
	ctx.arcTo(x+width,y+height,x+width-radius,y+height,radius);
	// draw bottom and bottom left corner
	ctx.arcTo(x,y+height,x,y+height-radius,radius);
	// draw left and top left corner
	ctx.arcTo(x,y,x+radius,y,radius);
	if(fill) {
		ctx.fill();
	}
	if(stroke){
		ctx.stroke();
	}
	ctx.restore();
}

Animating Particles on the Canvas

I have a ”Flying Bees” demo that shows how to create many instances of, say a circle, and then animate them.