Particle-системы

Particle-система — это совокупность множества мелких визуальных объектов (частиц), которые управляются единым механизмом анимации. В контексте ScrollMagic частицы не просто анимируются во времени, а привязываются к положению прокрутки страницы. Это позволяет создавать динамические сцены, реагирующие на действия пользователя.

Основные компоненты:

  • Контроллер (Controller) — управляет всеми сценами и синхронизацией со скроллом
  • Сцена (Scene) — определяет диапазон прокрутки, в котором происходит анимация
  • Рендерер частиц — отвечает за отрисовку (Canvas, SVG или DOM)
  • Система обновления — пересчитывает позиции и свойства частиц

Выбор технологии рендеринга

Canvas

Наиболее подходящий вариант для большого количества частиц (сотни и тысячи).

Преимущества:

  • Высокая производительность
  • Минимальная нагрузка на DOM
  • Гибкость при отрисовке

Недостатки:

  • Отсутствие нативной работы со стилями CSS
  • Более сложная логика

SVG

Подходит для небольшого количества частиц.

Преимущества:

  • Интеграция с DOM
  • Простота стилизации

Недостатки:

  • Падение производительности при большом количестве элементов

DOM-элементы

Используются редко, только для простых эффектов.


Базовая структура particle-системы

class Particle {
  constructor(x, y, size, speed) {
    this.x = x;
    this.y = y;
    this.size = size;
    this.speed = speed;
  }

  update(progress) {
    this.y += this.speed * progress;
  }

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

Создание системы:

const particles = [];

for (let i = 0; i < 200; i++) {
  particles.push(
    new Particle(
      Math.random() * canvas.width,
      Math.random() * canvas.height,
      Math.random() * 3,
      Math.random() * 2
    )
  );
}

Интеграция со ScrollMagic

Создание контроллера и сцены:

const controller = new ScrollMagic.Controller();

const scene = new ScrollMagic.Scene({
  triggerElement: "#trigger",
  duration: 1000
})
.addTo(controller);

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

scene.on("progress", (event) => {
  const progress = event.progress;

  updateParticles(progress);
  renderParticles();
});

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

Функция обновления должна учитывать прогресс прокрутки:

function updateParticles(progress) {
  particles.forEach(particle => {
    particle.update(progress);
  });
}

Рендеринг:

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

  particles.forEach(particle => {
    particle.draw(ctx);
  });
}

Контроль параметров через scroll progress

ScrollMagic предоставляет значение progress от 0 до 1. Это ключевой параметр для управления поведением частиц.

Примеры:

Изменение прозрачности

ctx.globalAlpha = progress;

Ускорение движения

particle.y += particle.speed * (1 + progress * 5);

Масштабирование

particle.size = baseSize * (1 + progress);

Генерация сложных эффектов

Параллакс-движение

Разные частицы движутся с разной скоростью:

particle.y += particle.speed * (progress * particle.depth);

Где depth — коэффициент “глубины”.


Взрыв (explosion effect)

particle.x += Math.cos(particle.angle) * progress * 100;
particle.y += Math.sin(particle.angle) * progress * 100;

Притяжение к точке

const dx = targetX - particle.x;
const dy = targetY - particle.y;

particle.x += dx * 0.05 * progress;
particle.y += dy * 0.05 * progress;

Оптимизация производительности

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

Оптимальное количество:

  • Canvas: до 2000
  • SVG: до 200

Использование requestAnimationFrame

Хотя ScrollMagic управляет прогрессом, отрисовку лучше синхронизировать:

function animate() {
  renderParticles();
  requestAnimationFrame(animate);
}

animate();

Минимизация перерасчетов

  • Не создавать объекты в циклах
  • Использовать переиспользование (object pooling)

Object Pooling

Создание и удаление частиц — дорогостоящая операция.

Решение:

const pool = [];

function getParticle() {
  return pool.length ? pool.pop() : new Particle(0, 0, 0, 0);
}

function releaseParticle(p) {
  pool.push(p);
}

Комбинирование с GSAP

ScrollMagic часто используется вместе с GSAP для сложных анимаций.

Пример:

const tween = gsap.to(particles, {
  duration: 1,
  y: "+=200",
  stagger: 0.01
});

new ScrollMagic.Scene({
  triggerElement: "#trigger",
  duration: 500
})
.setTween(tween)
.addTo(controller);

Реакция на пользовательские события

Изменение направления при прокрутке вверх

scene.on("update", (event) => {
  const direction = event.scrollDirection;

  particles.forEach(p => {
    p.speed = direction === "REVERSE" ? -Math.abs(p.speed) : Math.abs(p.speed);
  });
});

Использование WebGL (через библиотеки)

Для очень сложных систем применяются:

  • Three.js
  • PixiJS

ScrollMagic управляет только прогрессом:

scene.on("progress", (event) => {
  shader.uniforms.uProgress.value = event.progress;
});

Управление жизненным циклом частиц

Добавление “времени жизни”:

class Particle {
  constructor() {
    this.life = 1;
  }

  update(progress) {
    this.life -= 0.01 * progress;
  }

  isAlive() {
    return this.life > 0;
  }
}

Очистка:

particles = particles.filter(p => p.isAlive());

Синхронизация нескольких сцен

Можно создавать разные particle-эффекты для разных секций:

new ScrollMagic.Scene({
  triggerElement: "#section1",
  duration: 500
})
.on("progress", updateParticlesLayer1);

new ScrollMagic.Scene({
  triggerElement: "#section2",
  duration: 800
})
.on("progress", updateParticlesLayer2);

Композиция эффектов

Сложные сцены строятся через слои:

  • Фоновый слой (медленные частицы)
  • Средний слой (основное движение)
  • Передний слой (быстрые элементы)

Каждый слой имеет свой коэффициент:

particle.speed *= layerMultiplier;

Отладка и диагностика

Включение индикаторов ScrollMagic

scene.addIndicators();

Позволяет визуально видеть:

  • начало сцены
  • конец
  • текущий прогресс

Расширяемость системы

Particle-система должна быть модульной:

  • Отдельный класс для частиц
  • Отдельный менеджер
  • Отдельный рендерер

Пример менеджера:

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

  update(progress) {
    this.particles.forEach(p => p.update(progress));
  }

  render(ctx) {
    this.particles.forEach(p => p.draw(ctx));
  }
}

Типичные ошибки

  • Привязка анимации к времени вместо scroll progress
  • Слишком большое количество DOM-элементов
  • Отсутствие очистки canvas
  • Игнорирование производительности на мобильных устройствах
  • Создание частиц внутри обработчика scroll

Практический сценарий: “снег при прокрутке”

  1. Генерация частиц сверху
  2. Медленное падение
  3. Ускорение при увеличении scroll progress
particle.y += particle.speed * (0.5 + progress * 2);

Дополнительно:

  • лёгкое колебание по X
  • случайная прозрачность

Практический сценарий: “звёздное поле”

  • Частицы увеличиваются по мере прокрутки
  • Эффект приближения
particle.size = baseSize * (1 + progress * 3);
particle.y += particle.speed * progress * 10;

Масштабирование под разные устройства

  • Уменьшение количества частиц на мобильных
  • Использование devicePixelRatio
  • Ограничение FPS
const isMobile = window.innerWidth < 768;

const particleCount = isMobile ? 100 : 500;

Управление через параметры

Рекомендуется выносить настройки:

const config = {
  count: 300,
  speed: 2,
  size: 3,
  color: "#ffffff"
};

Это упрощает адаптацию и повторное использование системы.


Синхронизация с другими эффектами

Particle-системы часто комбинируются с:

  • fade-анимациями
  • transform (scale, rotate)
  • изменением фона

ScrollMagic позволяет синхронизировать всё через один progress.


Декомпозиция системы

Для крупного проекта:

  • Particle
  • ParticleEmitter
  • ParticleSystem
  • Renderer
  • ScrollController

Это позволяет:

  • масштабировать проект
  • переиспользовать компоненты
  • тестировать отдельные части системы