效果预览
在线Demo
核心代码
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" },
{ front: "#b3c7ff", back: "#8fa5e5" },
{ front: "#5c86ff", back: "#345dd1" },
];
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();