<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.