Let it snow!

Wednesday December 31, 2014

For the holiday season, I whipped up a quick HTML and JavaScript snow effect. It’s very simple, but I’ve decided to break it down for the beginners out there. I’m using jQuery, although it’s not too hard to accomplish the same thing with vanilla JavaScript. In this tutorial, I try to explain most things on a very basic level, but I still have a few assumptions about you knowing at least what variables, DOM/HTML elements, and some other things are.

Here’s a live demo of what we’re making.

Base Styling

First off, let’s discuss how we’re going to make a snowflake. It’s very simple: we’ll just use a div element for each flake. We will give each snowflake a random position within the window, a random size, and a random velocity. When a flake reaches the bottom of the page, we’ll reset it to the top of the page and give it a random x-position so that it doesn’t keep falling in the same spot.

Here’s some styling to give each flake the base characteristics. Later on, we’ll give each individual flake its own size and position.

The Snowstorm

I love encapsulating code into objects, even in Javascript. That’s why we’ll be going over the two parts: the Snowstorm and the Flakes. The Snowstorm will contain an array of all the snowflakes, as well as functions for generating and animating the flakes.

Here’s the constructor–the function called when we first create a new Snowstorm.

container is the DOM element which will hold all of our snowflakes. I’m using a shorthand if-else-statement here to check if an element with the id #snowstorm exists already. If it does, we’ll use that, otherwise we need to create it first and add it to the end of the body. Line 3 creates a blank array to hold snowflakes. Line 4 calls our next function to generate all the snowflakes. On line 5, we store this (which points to the current Snowstorm object) into a temporary variable, $this, because the context of this changes inside the setInterval function on line 6. On line 6, we are telling the browser to run our loop function 15 times per second.

Flake Generation

Let’s form some snow! Here we will generate the snowflakes.. sort of. We’ll create new Flake objects and put them in our flake array, but the actual html element creation isn’t done in this code.

In this code, we tackle a vital issue: how many snowflakes to generate? We shouldn’t specify a static number because then we’ll have large displays with a low concentration os snow and small displays with a high concentration of snow. To address this, I’m using a simple solution: the number of flakes is calculated as a percentage of the window area. More specifically, the number of flakes is %0.016 of the window area. For example, a 1920×1080 window will have 331 snowflakes. You can play with the percentage to change the density of snow. Lastly, we use a for loop to create the specified number of flakes, add them to the array, then call our future randomize function to give the flake a random position, velocity, and size. When creating the new flake, we pass in the container so that it knows where to put the flake.

The Loop

Finishing up the Snowstorm object: the loop. Earlier, we told the browser to call this loop function 15 times per second. It will update the positions of the snowflakes based on their velocities.

For each flake in our array, call its update function.

Randomization Helper

Onto the flakes! Well, almost. First, let’s take care of a little helper function. We will be doing a lot of randomization, so here’s a quick function to return a random integer between two given numbers (inclusive).

Flakes!

Okay, now a Flake! el is the div element. We create it then insert it into the DOM, at the end of the container element that we got from the snowstorm’s generate function. Initially, each flake will start out with basic default values. radius is for the flake size. x and y are the position within the window. dx and dy are the velocities for the x and y direction. The velocities are the amount of pixels that the flake will move on each update.

Randomize the Flakes

Recall from our Snowstorm.generate function that we randomize the flake after creating it. Here’s the function for that.

For a couple of our randomizations, you’ll see me divide by 10. This is due to our rand function only returning integers. In some cases, we want a little more variety in our randomization than just whole numbers. For example, instead of just having a radius of 1, 2, or 3, we can now have a radius of .5, 1.4, 2.6, and so on. (we now have one decimal place of precision)

This randomization may be the trickiest part of this tutorial, so I’ll break down why I chose each value:

The radius is half the size of the flake, so I want a good variety of random values to prevent having only 3 different sizes. The radius will range from .5 to 3.0 with a single decimal place of precision. If you want to provide your own range for snowflake sizes, remember to multiple the actual value by 10 such that a desired max radius of 6px is rand(5, 60).

The starting x and y position for each flake should be between 0 (top/left side of screen) and the window height/width (bottom/right side of screen).

We then set the CSS values for width and height, which are double the radius. We use border-radius to make the div circular. top and left are the position. We then give the element the class snowflake.

dx is the horizontal velocity. I wanted some flakes to move to the left and some to the right. This is achieved by either having a negative (left) or positive (right) dx. Recall that dx is the number of pixels that the flake will move each update. Also recall that we set our Snowstorm to update 15 times per second. This means that a flake with a dx of -.5 will move 7.5 pixels to the left every second. I use rand here to generate a velocity between -1 and 1 pixels per update, again with single decimal place precision (could be -.9, 0, .3, .9, etc.).

dy is the vertical velocity. Flakes should only be falling downwards, so no negative values here! I don’t want too much variation in the speed, so we’re only going to have a range of 1.8 to 2.4 pixels per update.

Updating Flake Position

Last, but not least, we need to update the flakes. On every update, the position will increase (or decrease) by the veocity (AKA how many pixels it moves per update). After changing the object’s variables, we update the actual CSS position. If the flake’s y position goes beyond the height of the window, then we reset it to the top of the page. We also give it a random x position to prevent the snowflakes from continually falling in the same spot.

Let it Snow!

That’s it! We’re done! Let’s start it up!

All Together Now

For completeness sake, let’s put it all together.

 

← Return to Blog