Чувствуете, что вашему веб-сайту не хватает чего-то… праздничного? Будь то регистрация пользователя, завершение задачи или просто нажатие кнопки «Праздновать!», взрыв конфетти — это классический способ добавить нотку восторга.
Сегодня мы разработаем легкий и высокопроизводительный эффект взрыва конфетти, используя API HTML5 Canvas. Никаких громоздких внешних библиотек не требуется — только один скрипт и немного желания.
Посмотрите Конфетти в Действии
Как Работает JavaScript Код для Конфетти
Скрипт динамически создает элемент <canvas>, который покрывает весь экран. При клике на элемент с классом .confetti скрипт вычисляет его центр и генерирует 150 уникальных частиц.
Каждая частица имеет свои:
- Физика: Скорость, гравитация и сопротивление воздуха применяются к каждой частице на каждом кадре.
- Эстетика: Рандомизированные цвета из подобранной палитры и различные размеры.
- Движение: Фактор вращения и поворот, чтобы имитировать падение настоящей бумаги.
- Жизненный цикл: Затухание прозрачности, благодаря которому частицы исчезают до того, как они будут удалены из памяти.
JavaScript Код
Вы можете интегрировать этот скрипт в свой проект.
<script src='confetti.js'></script>
Он обернут в IIFE (Immediately Invoked Function Expression) для поддержания чистоты глобального пространства имен.
(function () {
const PARTICLE_COUNT = 150;
const COLORS = [
'#ff0a54', '#ff477e', '#ff7096', '#ff85a1',
'#fbb1bd', '#f9bec7', '#3a86ff', '#8338ec',
'#ffbe0b', '#fb5607', '#06d6a0', '#118ab2',
];
const GRAVITY = 0.12;
const DRAG = 0.98;
const SPIN_DRAG = 0.97;
let canvas, ctx, particles, animId;
function createCanvas() {
canvas = document.createElement('canvas');
// Set styles to cover the viewport and ignore mouse events
canvas.style.cssText =
'position:fixed;top:0;left:0;width:100%;height:100%;pointer-events:none;z-index:2147483647';
document.body.appendChild(canvas);
ctx = canvas.getContext('2d');
resize();
window.addEventListener('resize', resize);
}
function resize() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
}
function randomBetween(a, b) {
return a + Math.random() * (b - a);
}
function createParticle(x, y) {
const angle = randomBetween(0, 2 * Math.PI);
const speed = randomBetween(6, 18);
return {
x: x,
y: y,
vx: Math.cos(angle) * speed,
vy: Math.sin(angle) * speed - randomBetween(2, 8),
w: randomBetween(6, 12),
h: randomBetween(4, 8),
color: COLORS[Math.floor(Math.random() * COLORS.length)],
rotation: randomBetween(0, 2 * Math.PI),
spin: randomBetween(-0.3, 0.3),
opacity: 1,
decay: randomBetween(0.006, 0.012),
};
}
function explode(originX, originY) {
if (!canvas) createCanvas();
// Restart animation if one is already running
if (animId) cancelAnimationFrame(animId);
particles = [];
for (let i = 0; i < PARTICLE_COUNT; i++) {
particles.push(createParticle(originX, originY));
}
animate();
}
function animate() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
for (let i = particles.length - 1; i >= 0; i--) {
const p = particles[i];
// Physics logic
p.vx *= DRAG;
p.vy *= DRAG;
p.vy += GRAVITY;
p.x += p.vx;
p.y += p.vy;
p.rotation += p.spin;
p.spin *= SPIN_DRAG;
p.opacity -= p.decay;
if (p.opacity <= 0) {
particles.splice(i, 1);
continue;
}
// Drawing logic
ctx.save();
ctx.translate(p.x, p.y);
ctx.rotate(p.rotation);
ctx.globalAlpha = p.opacity;
ctx.fillStyle = p.color;
ctx.fillRect(-p.w / 2, -p.h / 2, p.w, p.h);
ctx.restore();
}
if (particles.length > 0) {
animId = requestAnimationFrame(animate);
} else {
ctx.clearRect(0, 0, canvas.width, canvas.height);
animId = null;
}
}
// Global Click Listener
document.addEventListener('click', function (e) {
const trigger = e.target.closest('.confetti');
if (!trigger) return;
const rect = trigger.getBoundingClientRect();
const cx = rect.left + rect.width / 2;
const cy = rect.top + rect.height / 2;
explode(cx, cy);
});
})();
Руководство по Внедрению
-
Добавьте скрипт: Скопируйте приведенный выше код в файл
.jsи подключите его в конце<body>, или поместите его непосредственно в ваш HTML внутри тегов<script>. -
Пометьте ваш триггер: Вам не нужно писать дополнительный JavaScript для кнопок. Просто добавьте класс
confettiк любой кнопке, ссылке илиdiv, который вы хотите использовать:<button class='confetti'>Нажми меня!</button> -
Настройте:
- Хотите больше конфетти? Измените значение
PARTICLE_COUNT. - Хотите другую атмосферу? Обновите массив
COLORSс шестнадцатеричными кодами цветов вашего бренда. - Хотите более ‘плавающие’ конфетти? Уменьшите значение
GRAVITY.
- Хотите больше конфетти? Измените значение
Удачного празднования! 🥳

