Here's how you can add a snow animation with JavaScript to your site just for the festive season :)
See a demo by watching the tutorial here and for my thoughts on why it's a bad idea!
1. Setup Constants
Let's setup some variables to hold some info on the appearance of our snow animation.
const NUMBER_OF_SNOWFLAKES = 300;
const MAX_SNOWFLAKE_SIZE = 5;
const MAX_SNOWFLAKE_SPEED = 2;
const SNOWFLAKE_COLOUR = '#ddd';
const snowflakes = [];
We'll also create an empty array called snowflakes
which is going to keep track of all the individual snowflakes on the page.
2. Create a canvas
All our snowflakes are going to be drawn onto a canvas element so let's create that and drop it onto the current document.
const canvas = document.createElement('canvas');
canvas.style.position = 'absolute';
canvas.style.pointerEvents = 'none';
canvas.style.top = '0px';
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
document.body.appendChild(canvas);
const ctx = canvas.getContext('2d');
We're sizing the canvas to fit the entire window and setting the pointer-event
CSS property to none
so it makes the canvas invisible and the user can still click things behind it.
Finally, we'll get the 2d canvas context, which we can use to draw our snowflakes on.
But first, we need a function to generate a snowflake.
3. Create a snowflake
const createSnowflake = () => ({
x: Math.random() * canvas.width,
y: Math.random() * canvas.height,
radius: Math.floor(Math.random() * MAX_SNOWFLAKE_SIZE) + 1,
color: SNOWFLAKE_COLOUR,
speed: Math.random() * MAX_SNOWFLAKE_SPEED + 1,
sway: Math.random() - 0.5
});
This function will create and return a snowflake object which is at some random position on the page. We'll also create a random size (radius) for it, set its colour to the constant we defined and also give it a random speed with a minimum value.
In the second part of the tutorial, we introduce a sway
property in order to move the snowflake either left or right as it falls down the page.
Now we need a way to draw the snowflake onto the canvas.
4. Draw a snowflake
const drawSnowflake = snowflake => {
ctx.beginPath();
ctx.arc(snowflake.x, snowflake.y, snowflake.radius, 0, Math.PI * 2);
ctx.fillStyle = snowflake.color;
ctx.fill();
ctx.closePath();
};
We're just going to draw a circle with a radius as specified by the property on the snowflake object that's passed in.
5. Update a snowflake
const updateSnowflake = snowflake => {
snowflake.y += snowflake.speed;
snowflake.x += snowflake.sway;
if (snowflake.y > canvas.height) {
Object.assign(snowflake, createSnowflake());
}
};
Here, we'll take one of our snowflake objects and update its x and y positions on the page. If it gets to the bottom of the page, we'll re-assign the reference of the snowflake to a new snowflake object.
6. Animating snowflakes
const animate = () => {
ctx.clearRect(0, 0, canvas.width, canvas.height);
snowflakes.forEach(snowflake => {
updateSnowflake(snowflake);
drawSnowflake(snowflake);
});
requestAnimationFrame(animate);
};
The animate
function clears the current canvas and then loops through our array of snowflakes and updates their position, then draws them onto the canvas.
We can make a really smooth animation by simply calling this function repeatedly by passing it to requestAnimationFrame
.
Of course, we haven't put any snowflake objects into our snowflakes
array yet so let's populate those now and kick off the animation by calling the animate
function.
for (let i = 0; i < NUMBER_OF_SNOWFLAKES; i++) {
snowflakes.push(createSnowflake());
}
animate();
We should have a fully working snowfall animation on our page now!
7. Adding Event Listeners
If you try and resize your browser window at this point or scroll down to more content (if it exists on your page) then you'll notice that the snowfall effect is fixed to the top of the page and doesn't resize to fit the browser window.
Let's finish off our beautiful snowfall animation with a couple of event listeners to handle this.
window.addEventListener('resize', () => {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
});
window.addEventListener('scroll', () => {
canvas.style.top = `${window.scrollY}px`;
});
Because we've written everything in JavaScript with no extra HTML/CSS required, we can just copy the code and drop it into any site. For example, here's how it looks on Amazon's site:
Conclusion
As mentioned in the video, this is just a bit of fun and not something you should probably add to your site unless your company is insistent on sending your site back to the 1990s :)
Thanks for reading and be sure to check out the full tutorial here if you want more details:
Top comments (3)
Thank you! very useful
Nice script! I made a small tweak so the snow forms more uniformly across the viewport. Change the "y" calculation slightly and the snow won't appear so sparse up top and heavy at the bottom:
Cheers!
Instead of updating canvas top when scrolling, I've changed
position: absolute
toposition: fixed
check github.com/le-pepe/snow-effect