rainrainra.in/scripts/script.js
2024-04-26 16:14:57 -07:00

118 lines
2.8 KiB
JavaScript

const IMGS = [
"/img/rains/arch.png",
"/img/rains/bmo.png",
"/img/rains/cat.gif",
"/img/rains/demi.png",
"/img/rains/dnd.png",
"/img/rains/eattherich.png",
"/img/rains/gloomhaven.png",
"/img/rains/iron_throne.png",
"/img/rains/link.png",
"/img/rains/meddle.jpeg",
"/img/rains/moon.png",
"/img/rains/note.png",
"/img/rains/obsidian.png",
"/img/rains/outerwilds.png",
"/img/rains/piano.png",
"/img/rains/pirate.svg",
"/img/rains/ror.png",
"/img/rains/smashball.svg",
"/img/rains/ssa.png",
"/img/rains/svelte.png",
"/img/rains/usu.png",
];
const DROPLETS = 8;
const DROPLET_WIDTH_RANGE = [80, 120];
const DROPLET_DY_RANGE = [0.1, 0.4];
const DROPLET_DTHETA_RANGE = [-0.25, 0.25];
const DROPLET_INIT_THETA_RANGE = [-180, 180];
const makeDroplet = (src, width, x, y, theta, dtheta, dy) => {
const img = document.createElement("img");
img.style.position = "absolute";
img.style.width = `${width}px`;
img.src = src;
document.body.appendChild(img);
return {
img,
width,
theta,
pos: { x, y },
vel: { dy, dtheta },
};
};
const randBetween = (min, max) => Math.random() * (max - min) + min;
const update = (droplets, dt, boundedY) =>
droplets
.map((droplet) => {
return {
...droplet,
pos: { ...droplet.pos, y: droplet.pos.y + droplet.vel.dy * dt },
theta: droplet.theta + droplet.vel.dtheta * dt,
};
})
.map((droplet) => {
const {
pos: { y },
img,
} = droplet;
if (y >= boundedY) {
document.body.removeChild(img);
return null;
}
return droplet;
})
.filter((x) => x)
.map((droplet) => {
const {
img,
pos: { x, y },
theta,
} = droplet;
img.style.left = `${x}px`;
img.style.top = `${y}px`;
img.style.transform = `rotate(${theta}deg)`;
return droplet;
});
const buildRandomDroplet = () =>
makeDroplet(
IMGS[Math.floor(randBetween(0, IMGS.length))],
randBetween(...DROPLET_WIDTH_RANGE),
randBetween(0, window.innerWidth - DROPLET_WIDTH_RANGE[1]),
randBetween(-50, window.innerHeight / 8),
randBetween(...DROPLET_INIT_THETA_RANGE),
randBetween(...DROPLET_DTHETA_RANGE),
randBetween(...DROPLET_DY_RANGE),
);
window.onload = () => {
// cache 'em
IMGS.forEach((x) => {
((img) => (img.src = x))(new Image());
});
let droplets = Array(DROPLETS).fill().map(buildRandomDroplet);
let lastTimestamp = performance.now();
const next = (timestamp) => {
const dt = timestamp - lastTimestamp;
lastTimestamp = timestamp;
droplets = update(droplets, dt, window.innerHeight);
if (droplets.length != DROPLETS) {
droplets.push(buildRandomDroplet());
}
requestAnimationFrame(next);
};
requestAnimationFrame(next);
};