frontend/snow.js (60 lines of code) (raw):
// import jQuery from "jquery";
document.addEventListener('DOMContentLoaded', function() {
let itSnow = document.querySelectorAll('.festive').length;
if (itSnow) {
const footer = document.querySelector('footer');
const flakeDiameter = 6;
let width = window.innerWidth - flakeDiameter;
let height = footer.getBoundingClientRect().top + footer.offsetHeight - flakeDiameter;
let wind = 0;
function createSnowFlake() {
const x = Math.random() * width;
const y = Math.random() * height;
const el = document.createElement('div');
el.style.width = flakeDiameter + 'px';
el.style.height = flakeDiameter + 'px';
el.style.borderRadius = '4px';
el.style.backgroundColor = '#f7f7f7';
el.style.position = 'absolute';
el.style.top = -y + 'px';
el.style.left = x + 'px';
el.style.boxShadow = '1px 1px 2px';
el.style.zIndex = '5';
document.body.appendChild(el);
return { el, x, y };
}
function animate(flake) {
wind = Math.max(-0.1, Math.min(0.1, wind + Math.random() * 0.001 - (0.001 / 2)));
const newY = flake.y + (Math.random() * 2);
let newX = flake.x + Math.random() - (0.5 + wind);
if (newX < 0) {
newX = width;
} else if (newX > width + flakeDiameter) {
newX = flakeDiameter;
}
if (newY > height) {
flake.y = -10;
flake.x = Math.random() * width;
} else {
flake.y = newY;
flake.x = newX;
}
flake.el.style.top = flake.y + 'px';
flake.el.style.left = flake.x + 'px';
}
const flakes = Array.from({ length: 100 }, createSnowFlake);
window.addEventListener('resize', function() {
const newWidth = window.innerWidth - flakeDiameter;
const newHeight = footer.getBoundingClientRect().top + footer.offsetHeight - flakeDiameter;
flakes.forEach(function(flake) {
flake.x = (flake.x * (newWidth / width));
});
width = newWidth;
height = newHeight;
});
function tick() {
flakes.forEach(animate);
requestAnimationFrame(tick);
}
tick();
}
});