Skip to content

Instantly share code, notes, and snippets.

@patrickroberts
Last active December 3, 2021 19:42
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save patrickroberts/9749feceb490dea2d09e69254fa0b072 to your computer and use it in GitHub Desktop.
Save patrickroberts/9749feceb490dea2d09e69254fa0b072 to your computer and use it in GitHub Desktop.
Let it snow
// ==UserScript==
// @name Snow
// @version 1.0
// @description Make it snow
// @match *://*/*
// @grant none
// ==/UserScript==
(() => {
'use strict';
const pixels = () => screen.width * screen.height;
const length = () => Math.round(pixels() / 10000);
const array = [];
const container = document.createElement('div');
container.style.position = 'fixed';
container.style.left = container.style.top = '0';
container.style.width = '100vw';
container.style.height = '100vh';
container.style.zIndex = '9001';
container.style.pointerEvents = 'none';
document.body.append(container);
class Snowflake {
constructor(index = array.length, y = Math.random() * screen.height) {
this.index = index;
this.dx = (Math.random() - 0.5) / 6;
this.dy = (Math.random() + 0.5) / 6;
this.e = document.createElement('div');
this.e.style.position = 'fixed';
this.e.style.backgroundColor = 'white';
this.e.style.border = '1px solid lightgrey';
this.e.style.borderRadius = '50%';
this.e.style.left = `${this.x = Math.random() * screen.width}px`;
this.e.style.top = `${this.y = y}px`;
this.e.style.width = this.e.style.height = `${Math.random() * 5 + 1}px`;
container.appendChild(this.e);
}
update(elapsed) {
if (this.x < -6 || this.x > screen.width || this.y > screen.height) {
this.destroy();
} else {
this.e.style.left = `${this.x += this.dx * elapsed}px`;
this.e.style.top = `${this.y += this.dy * elapsed}px`;
}
}
destroy() {
this.e.remove();
if (array.length <= length()) {
array[this.index] = new Snowflake(this.index, -6);
} else if (array.length > 1) {
array[this.index] = array.pop();
array[this.index].index = this.index;
} else {
array.pop();
}
}
}
fill();
let prev = performance.now();
let id = requestAnimationFrame(update);
document.addEventListener('visibilitychange', () => {
if (document.visibilityState === 'visible') {
prev = performance.now();
id = requestAnimationFrame(update);
} else {
cancelAnimationFrame(id);
}
});
function fill() {
while (array.length < length()) {
array.push(new Snowflake());
}
}
function update(curr) {
const elapsed = curr - prev;
prev = curr;
id = requestAnimationFrame(update);
for (const snowflake of array) {
snowflake.update(elapsed);
}
fill();
}
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment