Canvas star effect

Past entries

As I said in my previous article, I've decided to share a little more code in my blog, so here is a code sample that you may want to check if you're doing some experiments with canvas.

English isn't my native language, therefore I don't think I would be able to write a full tutorial (writing articles is hard enough actually), but sharing some well-commented code shouldn't be a problem.

The effect allows you to make an animation of stars, with multiple depths of stars. This is the same technique I used in PxWars.

Here is a preview:

You can check the code here, or just copy/paste it from the box below:

	// Getting the canvas and its context
	// I don't make any verification about whether the browser supports 
	// canvas or not, as it's not the purpose of this code sample.
	var canvas = document.getElementById('canvas');
	if(canvas == null){
		alert('The canvas couldn't be found.');
	var ctx = canvas.getContext('2d');

	// Creating as much layers a needed
	var layers = [];
	for(var i = 0,alpha = 0, speed = 20 ; i < 4 ; i++, alpha += 1/4,speed += 20){

	// Drawing one layer
	function drawLayer(layer){
		// Calculating the offset module the canvas width.
		// On some browsers, using a huge offset can cause some troubles.
		var offset = ~~(layer.offset % canvas.width);

		// This is the tricky part. To create an offset on the layer, 
		// we translate the context as much as needed, and then we
		// draw it at the right position, so the pattern will have a 
		// different origin.;
		ctx.fillStyle = layer.pattern;

	// Making one layer
	function layerCycle(layer,elapsed){
		layer.offset += elapsed * layer.speed;

	var lastFrame =;
	function animationFrame(){
		// Calculating the time elapsed since the last frame was drawn.
		// We have to do this because we don't know what the frame rate
		// will be (we're not using setInterval or anything like that).
		var now =;
		var elapsed = (now - lastFrame) / 1000;
		lastFrame = now;
		// First, we have to clean the canvas. Let's just put a black background.
		ctx.fillStyle = 'black';
		// Then, we can update each layer
		for(var i in layers){

	// Now, we can finally start the animation, using the requestAnimationFrame API
	var requestAnimFrame = (function(){
		return  window.requestAnimationFrame       || 
				window.webkitRequestAnimationFrame || 
				window.mozRequestAnimationFrame    || 
				window.oRequestAnimationFrame      || 
				window.msRequestAnimationFrame     || 

	// As we need a function to call with requestAnimFrame(),
	// let's just use a simple closure.
			// Animation stops at the first error
			alert('An error occured: ' + e);

	// Creating a layer. A layer will be a canvas pattern that will
	// be used to draw on the main canvas.
	function createLayer(stars,starSize,alpha,speed){
		// To create a layer, we have to create a buffer canvas
		// to draw the stars on it.
		var layer = document.createElement('canvas');
		// Using the right dimensions. Note that you could also 
		// use smaller dimensions, but then you would be able
		// to see that it repeats itself.
		layer.width = canvas.width;
		layer.height = canvas.height;
		var layerCtx = layer.getContext('2d');
		// Drawing the stars on the buffer
		layerCtx.fillStyle = 'white';
		layerCtx.globalAlpha = alpha;
		for(var i = 0 ; i < stars ; i++){
			// We just have to ensure that the stars are not 
			// at the extreme side of the layer.
			// We also need to use integer coordinates to avoid
			// the blurring effect.
				~~(Math.random() * (layer.width - starSize)),
				~~(Math.random() * (layer.height - starSize)),
		// Creating the pattern
		var pattern = layerCtx.createPattern(layer,'repeat');
		// For layer that will be used, and some parameters
		return {
			pattern : pattern,
			speed : speed,
			offset : 0

There might be many ways to optimize it, or to add new effects, but I'll leave that to you :-)

< Fitting screen in HTML5 games
My Javascript toolbox >