Skip to content

Instantly share code, notes, and snippets.

@konecnyna
Last active May 22, 2021 17:29
Show Gist options
  • Save konecnyna/63dbaaa70fe6fe77ebfa0707e1cbb6b4 to your computer and use it in GitHub Desktop.
Save konecnyna/63dbaaa70fe6fe77ebfa0707e1cbb6b4 to your computer and use it in GitHub Desktop.
/** Adapted from https://codepen.io/pimskie/pen/jEVPNx **/
function Flake(x, y, maxSpeedConfig) {
const maxWeight = 5;
const maxSpeed = maxSpeedConfig || 3;
this.x = x;
this.y = y;
this.r = randomBetween(0, 1);
this.a = randomBetween(0, Math.PI);
this.aStep = 0.01;
this.weight = randomBetween(2, maxWeight);
this.alpha = this.weight / maxWeight;
this.speed = (this.weight / maxWeight) * maxSpeed;
this.update = function () {
this.x += Math.cos(this.a) * this.r;
this.a += this.aStep;
this.y += this.speed;
};
}
function init({ numFlakes, flakes, drawLines, imageSrc, maxSpeed }) {
let canvasElement = document.querySelector(".snow");
if (!canvasElement) {
canvasElement = document.createElement("canvas");
canvasElement.className = "snow";
canvasElement.style.backgroundColor = "transparent";
canvasElement.style.position = "absolute";
canvasElement.style.pointerEvents = "none";
document.body.appendChild(canvasElement);
}
const canvas = document.querySelector(".snow");
const ctx = canvas.getContext("2d");
canvasElement.style.backgroundColor = "transparent";
canvasElement.style.position = "absolute";
canvasElement.style.pointerEvents = "none";
var i = numFlakes,
flake,
x,
y;
while (i--) {
x = randomBetween(0, windowW, true);
y = randomBetween(0, windowH, true);
flake = new Flake(x, y, maxSpeed);
flakes.push(flake);
}
scaleCanvas(canvas);
loop(ctx, flakes, drawLines, imageSrc);
}
function scaleCanvas(canvas) {
canvas.width = windowW;
canvas.height = windowH;
}
function loop(ctx, flakes, drawLines, imageSrc) {
var i = flakes.length,
z,
dist,
flakeA,
flakeB;
// clear canvas
ctx.save();
ctx.setTransform(1, 0, 0, 1, 0, 0);
ctx.clearRect(0, 0, windowW, windowH);
ctx.restore();
// loop of hell
while (i--) {
flakeA = flakes[i];
flakeA.update();
if (drawLines) {
for (z = 0; z < flakes.length; z++) {
flakeB = flakes[z];
if (flakeA !== flakeB && distanceBetween(flakeA, flakeB) < 150) {
ctx.beginPath();
ctx.moveTo(flakeA.x, flakeA.y);
ctx.lineTo(flakeB.x, flakeB.y);
ctx.strokeStyle = "#444444";
ctx.stroke();
ctx.closePath();
}
}
}
ctx.beginPath();
if (imageSrc) {
const background = new Image();
background.src = imageSrc;
ctx.drawImage(background, flakeA.x, flakeA.y, 64, 64);
} else {
ctx.arc(flakeA.x, flakeA.y, flakeA.weight, 0, 2 * Math.PI, false);
ctx.fillStyle = "rgba(255, 255, 255, " + flakeA.alpha + ")";
}
ctx.fill();
if (flakeA.y >= windowH) {
flakeA.y = -flakeA.weight;
}
}
requestAnimationFrame(() => {
loop(ctx, flakes, drawLines, imageSrc);
});
}
function randomBetween(min, max, round) {
var num = Math.random() * (max - min + 1) + min;
if (round) {
return Math.floor(num);
} else {
return num;
}
}
function distanceBetween(vector1, vector2) {
var dx = vector2.x - vector1.x,
dy = vector2.y - vector1.y;
return Math.sqrt(dx * dx + dy * dy);
}
function makeRange(startDay, numberOfDays) {
return Array.from(new Array(numberOfDays), (x, i) => i + startDay);
}
function validateDate(month, days) {
const now = new Date();
return days.includes(now.getDate()) && now.getMonth() == month - 1;
}
const windowW = window.innerWidth;
const windowH = window.innerHeight;
console.log("Loaded ha-snow.js");
const isOctober = validateDate(11, makeRange(1, 31));
const isDecember = validateDate(12, makeRange(1, 25));
if (isOctober) {
console.log("Spooky enabled!");
init({
windowW,
windowH,
numFlakes: 5,
flakes: [],
drawLines: false,
imageSrc: "http://clipart-library.com/images/M8iGa75ca.png",
maxSpeed: 1,
});
} else if (isDecember) {
console.log("Snow enabled!");
init({
windowW,
windowH,
numFlakes: 20,
flakes: [],
drawLines: false,
maxSpeed: 3,
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment