SnowFall in Canvas

100 flakes with different sizes fly in chaotic Brownian motion.

by spmbt

HTML

<canvas id="canvas" width="480" height="640"></canvas>
<button>Toggle Motion</button>

JavaScript

var canvas = document.getElementById('canvas')
	,Snowflake = function(h){
		this.width = canvas.width;
		this.height = canvas.height;
		this.vxCommon = .5;
		this.vyCommon = .8;
		this.radius = h.radius;
		this.x = h.x;
		this.y = h.y;
		this.vx = h.vx;
		this.vy = h.vy;
    },
    random = function(n){return n * Math.random();}
    ,randRad
    ,snowflakes = Array.apply(0, Array(100)).map(function(){return new Snowflake({
        radius: randRad = 3 + random(7)
        ,x: randRad + random(canvas.width - 2* randRad)
        ,y: randRad + random(canvas.height - 2* randRad)
        ,vx: -2 + random(4)
        ,vy: -2 + random(4)
        ,expansion: 50 + random(200)
    });})
	,cont = canvas.getContext('2d'), noStopMotion =1, startMotion;

    (startMotion = function(){ //render all
        var now = +new Date();
		cont.fillStyle = '#aab1cd';
		cont.fillRect(0, 0, canvas.width, canvas.height);
		cont.fillStyle = '#cdd1df';

        snowflakes.forEach(function(val, i, arr){ //render flake
            val.date = val.date || now;
            var dt = now - val.date;
            val.y += dt * (val.vy + val.vyCommon + val.radius *.2) / 40;
            val.y -= val.height * (val.y / val.height |0);
            val.x += dt * (val.vx + val.vxCommon + val.radius *.1) / 40;
            val.x -= val.width * (val.x / val.width |0);
            val.vx += (-.1 + random(.2))*.8;
            val.vy += (-.1 + random(.2))*.8;

            cont.beginPath();
            cont.arc(val.x, val.y, val.radius, 0, 2 * Math.PI, false);
            cont.fill();

            val.date = now;
        });
		noStopMotion && setTimeout(arguments.callee, 30);
	})();
document.querySelector('button').addEventListener('click',function(){if(noStopMotion = noStopMotion ?0:1) startMotion()},!1);