<canvas id="mycan"></canvas>
html,
body,
canvas {
  width: 100%;
  height: 100%;
  overflow: hidden;
}
const canvas = document.getElementById("mycan");
const ctx = canvas.getContext("2d");
const confettiCount = 20;
const gravityConfetti = 0.3;
const gravitySequins = 0.55;
const dragConfetti = 0.075;
const dragSequins = 0.02;
const terminalVelocity = 3;
const randomRange = (min, max) => Math.random() * (max - min) + min;

canvas.setAttribute("width", window.innerWidth);
canvas.setAttribute("height", window.innerHeight);

const colors = [
	{ front: "#7b5cff", back: "#6245e0" }, // Purple
	{ front: "#b3c7ff", back: "#8fa5e5" }, // Light Blue
	{ front: "#5c86ff", back: "#345dd1" }, // Darker Blue
];
const confettis = [];

class Confetto {
	constructor(cx, cy) {
		this.randomModifier = randomRange(0, 99);
		this.color = colors[Math.floor(randomRange(0, colors.length))];
		this.dimensions = { x: randomRange(5, 9), y: randomRange(8, 15) };
		this.clients = { x: cx, y: cy };
		this.position = { x: cx, y: cy };
		this.scale = { x: 1, y: 1 };
		this.rotation = randomRange(0, 2 * Math.PI);
		this.velocity = { x: randomRange(-9, 9), y: -randomRange(6, 11) };
	}

	update() {
		this.velocity.x -= this.velocity.x * dragConfetti;
		this.velocity.y = Math.min(
			this.velocity.y + gravityConfetti,
			terminalVelocity
		);
		this.velocity.x += Math.random() > 0.5 ? Math.random() : -Math.random();

		this.position.x += this.velocity.x;
		this.position.y += this.velocity.y;

		this.scale.y = Math.cos((this.position.y + this.randomModifier) * 0.09);
	}
}

function render() {
	ctx.fillStyle = "#fff";
	ctx.fillRect(0, 0, canvas.width, canvas.height);
	confettis.forEach(drawConfetti);
	window.requestAnimationFrame(render);
}

function drawConfetti(confetti, index) {
	confetti.forEach((confetto, index2) => {
		let width = confetto.dimensions.x * confetto.scale.x;
		let height = confetto.dimensions.y * confetto.scale.y;

		ctx.translate(confetto.position.x, confetto.position.y);
		ctx.rotate(confetto.rotation);

		confetto.update();

		ctx.fillStyle =
			confetto.scale.y > 0 ? confetto.color.front : confetto.color.back;
		ctx.fillRect(-width / 2, -height / 2, width, height);
		ctx.setTransform(1, 0, 0, 1, 0, 0);

		if (confetto.position.y >= canvas.height) {
			confetti.splice(index2, 1);
		}
	});
	if (confetti.length === 0) {
		confettis.splice(index, 1);
	}
}

function clickFn({ clientX, clientY }) {
	let confetti = [];
	for (let i = 0; i < confettiCount; i++) {
		confetti.push(new Confetto(clientX, clientY));
	}
	confettis.push(confetti);
}

canvas.addEventListener("click", clickFn);

render();

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.