Personal and Professional Blog of Rich Hauck

Playing with Snow

by: Rich Hauck


For a recent project I had to animate snow, and it was the perfect opportunity to revisit a Processing Java applet I wrote several years ago. This time around, I coded it in HTML5 canvas.

You can view the snowflake canvas here

It’s a simple script that sets random properties on a Snowflake class. Once the snowflake reaches the bottom, it’s repositioned at the top with new random properties. Each snowflake animated down according to a sine wave (along with a little variation from the user’s mouse position). I’m using¬†window.requestAnimationFrame and having it fallback to setInterval(), if necessary.

It’s by no means perfect. Frankly, it reminds me of abstract painting–while I can minify and optimize the code, it may never be finished, as there are so many directions one can take it in.

Feel free to use the code in your project if you find it useful.

window.addEventListener('load', init, false);

var canvas;

function init(){
	canvas = document.getElementById("myCanvas");
	if (canvas.getContext){
	} else {
    	console.log("Canvas not supported");
function main(canvas){
	var ctx = canvas.getContext("2d");
    var mouseX = 0;
	var canvasWidth = canvas.width;
	var canvasHeight = canvas.height;
    var flakes = new Array();
	var COUNT = 100;
	var interval;

    canvas.addEventListener("mousemove", onMouseMove, false);

    // create snowflakes
    for(var i = 0; i <= COUNT; i++){
		flakes[i] = new Snowflake(canvasWidth, canvasHeight);
    function onEnterFrame(){
        intervalId = requestAnimFrame(onEnterFrame);
    //interval = setInterval(draw, 30);

	function draw() {
		for(var i = 0; i < COUNT; i++){ 			flakes[i].draw(ctx, mouseX); 		} 	}     function onMouseMove(evt){         mouseX = evt.clientX;     } 	function clear(){ 		ctx.clearRect(0, 0, canvasWidth, canvasHeight); 	} } 

Here’s the class:

 function Snowflake(canvasWidth, canvasHeight){     this.canvasWidth = canvasWidth; 	this.canvasHeight = canvasHeight;     // create random public values for positioning     this.x = Math.random()*canvasWidth;     this.y = Math.random()*canvasHeight;     this.radius = Math.round(Math.random()*5 + 5);     this.alpha = this.radius*0.1;     this.speed = Math.round((Math.random()*2)+(this.radius*0.2)); //chooses random speed to fall and factors size of snow. Larger size=faster drop     var xPos = this.x;     var yPos = this.y;     var bottom = this.canvasHeight + this.radius*2;     var i = 0;     /**     * Drawing engine.     * @param ctx Context     * @param mouseX Mouse's x-position on canvas     */ 	this.draw = function draw(ctx, mouseX){;         ctx.translate(this.x, this.y);         ctx.beginPath();         yPos += this.speed;         var sway = 60; //amount the snowflakes shift from side-to-side         var wind =((this.canvasWidth/2)-(mouseX))*.2; //value from 80 to -80         console.log(wind);         var xPos = Math.sin(i*.04)*sway + wind;         ctx.arc(xPos, yPos, this.radius*1.2, 0, 2 * Math.PI, false);         ctx.fillStyle = "rgba(255, 255, 255, "+this.alpha+")";         ctx.fill();         ctx.closePath();         ctx.restore();         i++;         if(yPos > bottom){
    * Resets properties of snowflake and repositions above visible area.
    this.reset = function reset(){
        this.x = Math.random()*this.canvasWidth;
        this.y = this.radius*-1;
        yPos = this.y;
        xPos = this.x;
        this.radius = Math.round(Math.random()*5 + 5);
        this.alpha = this.radius*0.1;
        bottom = this.canvasHeight + this.radius*2;
        this.speed = (Math.random()*.2)+(this.radius*0.2); //chooses random speed to fall and factors size of snow. Larger size=faster drop
        i = 0;

Leave a Reply

Your email address will not be published. Required fields are marked *

About Rich Hauck

Rich Hauck

I'm a creative technologist at Hauck Interactive, Inc. and an adjunct instructor at HACC. I live in Harrisburg, Pa. with my wife and three boys. I enjoy good coffee, Trappist beers, Orioles baseball, and good design.