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

При работе с библиотекой ScrollMagic ключевым аспектом становится оптимизация производительности, особенно когда на странице создаётся множество сцен. Каждая сцена добавляет слушатели событий и вычисления на каждом скролле, что может привести к заметной нагрузке на браузер.

Минимизация количества сцен

Основной принцип — не создавать сцены без необходимости. Если несколько элементов имеют одинаковое поведение при скролле, их можно объединить в одну сцену и управлять изменениями через CSS-классы или функции коллбэков.

Пример объединения нескольких анимаций:

const controller = new ScrollMagic.Controller();

const elements = document.querySelectorAll('.animate');
const scene = new ScrollMagic.Scene({
  triggerElement: '#trigger',
  duration: 500
})
.setClassToggle(elements, 'visible')
.addTo(controller);

Вместо создания отдельной сцены для каждого элемента, одна сцена управляет всеми сразу.

Использование triggerHook и duration с умом

  • triggerHook — положение триггера относительно окна. Значение 0 запускает сцену в верхней части окна, 1 — внизу.
  • duration — длина сцены. Чем больше длительность, тем дольше ScrollMagic отслеживает событие. Установка слишком больших значений для каждой сцены может серьёзно замедлить скроллинг.

При работе с большим количеством элементов рекомендуется задавать минимально возможную длительность и точные триггеры.

Lazy initialization и динамическое создание сцен

Создание всех сцен сразу для длинных страниц с сотнями элементов приводит к высокой нагрузке на рендер. Решение — создавать сцены только когда они близки к видимости.

const elements = document.querySelectorAll('.animate');

elements.forEach(el => {
  const observer = new IntersectionObserver((entries, obs) => {
    entries.forEach(entry => {
      if (entry.isIntersecting) {
        new ScrollMagic.Scene({
          triggerElement: el,
          duration: 300
        })
        .setClassToggle(el, 'visible')
        .addTo(controller);

        obs.unobserve(el);
      }
    });
  });

  observer.observe(el);
});

Такой подход снижает количество активных сцен и уменьшает нагрузку на обработку скролла.

Использование tween вместо onEnter/onLeave для сложных анимаций

Создание сцен с коллбэками onEnter и onLeave для каждого элемента может привести к множественным вызовам функций при быстром скролле. Более производительный способ — использование GSAP-твинов или других CSS-анимаций, которые ScrollMagic контролирует напрямую через setTween.

const tween = gsap.to('.box', {x: 500, rotation: 360, duration: 1});

new ScrollMagic.Scene({
  triggerElement: '.box',
  duration: 400
})
.setTween(tween)
.addTo(controller);

Твины обрабатываются GPU и браузерными оптимизациями, что снижает нагрузку по сравнению с множественными JS-коллбэками.

Отмена сцены и удаление слушателей

Если элемент больше не нужен на странице или удаляется из DOM, важно отключать сцены, чтобы ScrollMagic не продолжал слушать события скролла для этих элементов:

scene.destroy(true); // true — удаляет все слушатели и сбрасывает изменения

Контроллеры и множественные страницы

Для сложных страниц с разными секциями можно создавать несколько контроллеров, каждый из которых управляет своей областью. Это снижает общий объём вычислений при скролле, так как каждая часть страницы обрабатывается локально.

const mainController = new ScrollMagic.Controller();
const sectionController = new ScrollMagic.Controller({container: '#section'});

// Сцены для основной страницы
new ScrollMagic.Scene({...}).addTo(mainController);

// Сцены для отдельной секции
new ScrollMagic.Scene({...}).addTo(sectionController);

Отслеживание производительности

Для оценки нагрузки рекомендуется использовать:

  • Chrome DevTools → Performance для анализа времени обработки событий scroll и paint.
  • Метрики FPS и задержек анимации при быстром скролле.

Цель — поддерживать минимум 50–60 кадров в секунду, иначе пользовательский опыт заметно ухудшается.

Практические рекомендации

  1. Объединять сцены для нескольких элементов, если они имеют одинаковый эффект.
  2. Создавать сцены лениво через IntersectionObserver.
  3. Предпочитать твины вместо JS-коллбэков для анимаций.
  4. Удалять сцены, если элемент исчезает или перестаёт быть актуальным.
  5. Минимизировать длительность сцены и правильно настраивать triggerHook.
  6. Делить сцены между несколькими контроллерами, если страница длинная и сложная.

Эти методы позволяют ScrollMagic оставаться быстрым даже при работе с сотнями сцен и динамическим контентом.