Skip to content

Instantly share code, notes, and snippets.

@kirkegaard
Created December 21, 2020 21:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kirkegaard/8911e9b3f847829c7c971604d92fa526 to your computer and use it in GitHub Desktop.
Save kirkegaard/8911e9b3f847829c7c971604d92fa526 to your computer and use it in GitHub Desktop.
// Canvas things
const canvas = document.querySelector("#snow");
const ctx = canvas.getContext("2d");
let ctxLayers = [];
let ctxHeight = 0;
let ctxWidth = 0;
// FPS things
const FPS = 60;
const FPS_TIME = (1000 / 60) * (60 / FPS) - (1000 / 60) * 0.5;
// Time things
let reqanim = null;
let time = 0;
// Context things
let SNOW_AMOUNT = 100;
/**
* Get random number between two numbers
*/
const rand = (min, max) => Math.floor(Math.random() * (max - min + 1) + min);
/**
* Normalize value between two numbersä
*/
const normalize = (val, min, max) => (val - min) / (max - min);
/**
* The Snowflake
*/
const SnowFlake = (options) => {
let { x, y, radius, velocity } = options;
let opacity = 1;
const update = () => {
r = velocity * 0.005;
y += Math.abs(velocity * 0.009) + 1;
x += Math.cos(time * r * 0.005) * r * 2;
opacity = normalize(y, ctxHeight, (ctxHeight / 100) * 20);
if (y > ctxHeight + radius || opacity <= 0) {
y = rand(-ctxHeight / 2, -radius);
x = rand(0, ctxWidth);
}
};
const draw = () => {
ctx.beginPath();
ctx.arc(x, y, radius, 0, 2 * Math.PI);
ctx.fillStyle = `rgba(255, 255, 255, ${opacity})`;
ctx.fill();
ctx.closePath();
};
return { update, draw };
};
/**
* The loop
* Handles time and update/draw loop
*/
const loop = (utime) => {
if (utime - time < FPS_TIME) {
reqanim = requestAnimationFrame(loop);
return;
}
ctx.clearRect(0, 0, ctxWidth, ctxHeight);
ctxLayers.forEach((layer) => {
layer.forEach((item) => {
item.update();
item.draw();
});
});
time = utime;
reqanim = requestAnimationFrame(loop);
};
/**
* On window Resize
*/
const onResize = () => {
canvas.width = ctxWidth = window.innerWidth;
canvas.height = ctxHeight = window.innerHeight;
};
/**
* Initialize all the things
*/
const init = () => {
// Handle window resize
window.addEventListener("resize", onResize);
onResize();
// ctx.shadowColor = "white";
// ctx.shadowBlur = 5;
// Generate a bunch of flakes an throw then into the layer stack
const SnowFlakes = [...Array(SNOW_AMOUNT)].map(() => {
return SnowFlake({
y: rand(-ctxHeight, ctxHeight),
x: rand(0, ctxWidth),
radius: rand(2, 6),
velocity: rand(-50, 50),
});
});
ctxLayers.push(SnowFlakes);
reqanim = requestAnimationFrame(loop);
};
init();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment