Анимация частиц

Анимация частиц — это подход, при котором большое количество небольших объектов (частиц) управляются как единая система. Каждая частица обладает минимальным набором свойств: координаты, скорость, размер, прозрачность, цвет и время жизни. Вместе они формируют визуально сложные эффекты: дым, огонь, искры, снег, дождь.

В контексте библиотеки anime.js частицы не являются встроенной сущностью, поэтому система строится вручную на основе массивов объектов и анимации их свойств.


Структура частицы

Базовая модель частицы:

const particle = {
  x: 0,
  y: 0,
  vx: 0,
  vy: 0,
  size: 5,
  opacity: 1,
  life: 100
};

Ключевые параметры:

  • x, y — позиция на экране
  • vx, vy — скорость движения
  • size — размер
  • opacity — прозрачность
  • life — оставшееся время жизни

Генерация массива частиц

Система частиц обычно представляется массивом:

const particles = [];

function createParticle(x, y) {
  return {
    x,
    y,
    vx: (Math.random() - 0.5) * 4,
    vy: (Math.random() - 0.5) * 4,
    size: Math.random() * 6 + 2,
    opacity: 1,
    life: 100
  };
}

Добавление частиц:

for (let i = 0; i < 100; i++) {
  particles.push(createParticle(300, 300));
}

Отрисовка частиц

Для визуализации чаще всего используется <canvas>:

const canvas = document.querySelector('canvas');
const ctx = canvas.getContext('2d');

function drawParticles() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);

  particles.forEach(p => {
    ctx.beginPath();
    ctx.arc(p.x, p.y, p.size, 0, Math.PI * 2);
    ctx.fillStyle = `rgba(255, 100, 100, ${p.opacity})`;
    ctx.fill();
  });
}

Обновление состояния частиц

Каждый кадр частицы обновляют свои параметры:

function updateParticles() {
  particles.forEach(p => {
    p.x += p.vx;
    p.y += p.vy;
    p.life--;
    p.opacity = p.life / 100;
  });
}

Удаление “мертвых” частиц:

particles = particles.filter(p => p.life > 0);

Использование anime.js для анимации частиц

Библиотека anime.js позволяет анимировать свойства объектов, включая пользовательские:

anime({
  targets: particles,
  x: p => p.x + (Math.random() - 0.5) * 200,
  y: p => p.y + (Math.random() - 0.5) * 200,
  opacity: 0,
  size: 0,
  duration: 2000,
  easing: 'easeOutExpo',
  update: drawParticles
});

Здесь:

  • anime.js управляет изменением координат и прозрачности
  • функция update перерисовывает сцену на каждом кадре

Эффект взрыва

Типичный эффект — разлет частиц из одной точки:

function explode(x, y) {
  const explosionParticles = [];

  for (let i = 0; i < 50; i++) {
    explosionParticles.push({
      x,
      y,
      angle: Math.random() * Math.PI * 2,
      distance: Math.random() * 150,
      size: Math.random() * 4 + 2,
      opacity: 1
    });
  }

  anime({
    targets: explosionParticles,
    x: p => p.x + Math.cos(p.angle) * p.distance,
    y: p => p.y + Math.sin(p.angle) * p.distance,
    opacity: 0,
    size: 0,
    duration: 1200,
    easing: 'easeOutCubic',
    update: () => drawExplosion(explosionParticles)
  });
}

След за курсором (trail effect)

Создание шлейфа за движением мыши:

document.addEventListener('mousemove', e => {
  particles.push(createParticle(e.clientX, e.clientY));

  anime({
    targets: particles[particles.length - 1],
    opacity: 0,
    size: 0,
    duration: 1000,
    easing: 'linear',
    complete: () => particles.shift()
  });
});

Гравитация и физика

Добавление простейшей физики:

const gravity = 0.2;

function updateParticles() {
  particles.forEach(p => {
    p.vy += gravity;
    p.x += p.vx;
    p.y += p.vy;
    p.life--;
  });
}

Эффекты:

  • падение частиц вниз
  • имитация дождя или снега
  • более реалистичное движение

Турбулентность и шум

Для усложнения движения:

p.vx += (Math.random() - 0.5) * 0.2;
p.vy += (Math.random() - 0.5) * 0.2;

Это создаёт эффект:

  • дыма
  • пламени
  • магических частиц

Управление большим количеством частиц

При работе с сотнями и тысячами элементов важно:

1. Минимизировать количество объектов anime.js

  • Лучше анимировать группы, чем каждую частицу отдельно

2. Использовать requestAnimationFrame

  • Для обновления логики:
function loop() {
  updateParticles();
  drawParticles();
  requestAnimationFrame(loop);
}

loop();

3. Ограничивать количество частиц

if (particles.length > 500) {
  particles.splice(0, 100);
}

Цветовые переходы

Анимация цвета через anime.js:

anime({
  targets: particles,
  color: ['#ff0000', '#ffff00'],
  duration: 2000,
  easing: 'linear'
});

При использовании canvas цвет обычно вычисляется вручную:

ctx.fillStyle = `hsl(${p.life * 3}, 100%, 50%)`;

Комбинирование эффектов

Система частиц раскрывается при комбинировании:

  • взрыв + гравитация = фейерверк
  • турбулентность + fade-out = дым
  • след + easing = плавный хвост

Пример:

anime({
  targets: particles,
  x: p => p.x + Math.cos(p.angle) * 100,
  y: p => p.y + Math.sin(p.angle) * 100,
  opacity: [1, 0],
  size: [5, 0],
  easing: 'easeOutQuad',
  duration: 1500,
  update: drawParticles
});

Оптимизация рендеринга

Ключевые техники:

  • использование одного canvas вместо множества DOM-элементов
  • отключение теней и сложных эффектов
  • батчинг отрисовки
  • минимизация аллокаций объектов

Практическая архитектура

Типичная структура системы:

class ParticleSystem {
  constructor() {
    this.particles = [];
  }

  add(x, y) {
    this.particles.push(createParticle(x, y));
  }

  update() {
    this.particles.forEach(p => {
      p.x += p.vx;
      p.y += p.vy;
      p.life--;
    });

    this.particles = this.particles.filter(p => p.life > 0);
  }

  draw(ctx) {
    this.particles.forEach(p => {
      ctx.beginPath();
      ctx.arc(p.x, p.y, p.size, 0, Math.PI * 2);
      ctx.fill();
    });
  }
}

Интеграция с anime.js позволяет гибко управлять поведением:

  • запуск эффектов по событиям
  • управление временными интервалами
  • комбинирование easing-функций

Управление временем жизни

Вместо линейного уменьшения:

p.opacity = Math.pow(p.life / 100, 2);

Это даёт:

  • плавное затухание
  • более естественный визуальный результат

Итеративное развитие системы

Система частиц обычно развивается по этапам:

  1. Простое движение
  2. Добавление случайности
  3. Введение физики
  4. Оптимизация
  5. Сложные эффекты и композиции

Такой подход позволяет контролировать сложность и производительность, постепенно создавая насыщенные визуальные сцены.