Рефакторинг существующего кода

ScrollMagic — это библиотека для создания эффектов прокрутки, позволяющая привязывать анимации к положению скролла. Центральным элементом являются сцены (Scene) и контроллеры (Controller). Контроллер управляет всеми сценами на странице, обеспечивая синхронизацию их поведения с прокруткой.

const controller = new ScrollMagic.Controller();

const scene = new ScrollMagic.Scene({
  triggerElement: "#section1", // элемент, при котором сцена активируется
  duration: 300,               // длина сцены в пикселях
  triggerHook: 0.5             // точка срабатывания на экране (0 — верх, 1 — низ)
})
.setClassToggle("#section1", "active") // добавление класса при активации сцены
.addTo(controller);

Ключевые моменты:

  • triggerElement — элемент, с которого начинается сцена.
  • duration — длина действия сцены.
  • triggerHook — положение на экране, где сцена считается активной.
  • setClassToggle и setTween позволяют запускать анимации и менять стили.

Оптимизация существующих сцен

При работе с большим числом сцен важно минимизировать дублирование кода. Часто встречается ситуация, когда несколько элементов получают одинаковое поведение. Вместо создания множества сцен вручную, применяют итерацию по элементам:

document.querySelectorAll(".animate").forEach(el => {
  new ScrollMagic.Scene({
    triggerElement: el,
    triggerHook: 0.8
  })
  .setClassToggle(el, "visible")
  .addTo(controller);
});

Преимущества такого подхода:

  • Снижение повторяющегося кода.
  • Легкость добавления новых элементов на страницу.
  • Централизованное управление настройками.

Использование Tween для анимаций

ScrollMagic тесно интегрируется с библиотекой GSAP, что позволяет задавать сложные анимации. Основная схема:

const tween = gsap.to("#box", { x: 500, rotation: 360, duration: 2 });

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

Принципы рефакторинга при использовании Tween:

  1. Вынести повторяющиеся анимации в функции.
  2. Использовать динамическое связывание элементов.
  3. Применять объектные структуры для хранения параметров анимаций:
const animations = [
  { el: "#box1", x: 300, rotation: 180 },
  { el: "#box2", x: 500, rotation: 360 },
];

animations.forEach(anim => {
  const tween = gsap.to(anim.el, { x: anim.x, rotation: anim.rotation });
  new ScrollMagic.Scene({
    triggerElement: anim.el,
    duration: 300
  })
  .setTween(tween)
  .addTo(controller);
});

Такой подход упрощает управление анимациями и делает код более читабельным.


Контроллеры и производительность

Обычно на странице создают один контроллер ScrollMagic. Несколько контроллеров создают лишнюю нагрузку и могут приводить к конфликтам. Рекомендуется:

  • Один глобальный контроллер для всех сцен.
  • Настройка refreshInterval контроллера при динамическом изменении DOM:
const controller = new ScrollMagic.Controller({ refreshInterval: 100 });
  • Использование scene.destroy() для удаления сцен, которые больше не нужны.

Рефакторинг триггеров и хук-позиции

Часто сцены имеют одинаковый triggerHook. Чтобы избежать повторов:

const defaultHook = 0.7;

document.querySelectorAll(".section").forEach(el => {
  new ScrollMagic.Scene({
    triggerElement: el,
    triggerHook: defaultHook
  })
  .setClassToggle(el, "active")
  .addTo(controller);
});

Использование переменной defaultHook облегчает изменение логики прокрутки для всей страницы.


Удаление дублирующегося кода

Примеры повторяющихся паттернов:

  • Сцены с одинаковыми duration.
  • Сцены с одинаковыми классами для toggle.
  • Сцены с одинаковыми tween-анимациями.

Решение:

  1. Создать фабрику сцен:
function createScene(el, duration = 300, hook = 0.8, className = "visible") {
  return new ScrollMagic.Scene({
    triggerElement: el,
    duration: duration,
    triggerHook: hook
  })
  .setClassToggle(el, className)
  .addTo(controller);
}

document.querySelectorAll(".animate").forEach(el => createScene(el));
  1. Вынести общие настройки в объект:
const defaultSceneSettings = {
  duration: 300,
  triggerHook: 0.8,
  className: "visible"
};

function createScene(el, settings = defaultSceneSettings) {
  return new ScrollMagic.Scene({
    triggerElement: el,
    duration: settings.duration,
    triggerHook: settings.triggerHook
  })
  .setClassToggle(el, settings.className)
  .addTo(controller);
}

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


Интеграция с динамическим контентом

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

function initScenesForNewElements(selector) {
  document.querySelectorAll(selector).forEach(el => {
    if (!el.dataset.sceneInitialized) {
      createScene(el);
      el.dataset.sceneInitialized = true;
    }
  });
}

// Например, после AJAX-загрузки
initScenesForNewElements(".dynamic-animate");

Использование data-атрибутов предотвращает дублирование сцен для одних и тех же элементов.


Обработка нескольких анимаций на одном элементе

Иногда элементу нужно несколько эффектов при прокрутке:

const tl = gsap.timeline();
tl.to("#box", { x: 200, duration: 1 })
  .to("#box", { rotation: 180, duration: 1 });

new ScrollMagic.Scene({
  triggerElement: "#box",
  duration: 400
})
.setTween(tl)
.addTo(controller);

Рефакторинг:

  • Выносить timeline в отдельную функцию.
  • Использовать массив объектов для параметров каждой анимации.
  • Автоматически связывать их через цикл.

Логирование и отладка

ScrollMagic предоставляет методы для отладки:

  • .addIndicators() показывает на странице точки триггера и duration сцены.
  • Консольное логирование scene.on("enter", () => console.log("scene entered")).

Рефакторинг кода с большим числом сцен требует:

  • Включение индикаторов на этапе разработки.
  • Группировка логов по секциям.
  • Отключение индикаторов в продакшене.

Итоговые рекомендации по рефакторингу

  • Централизовать контроллер.
  • Использовать итерации и фабрики для сцен.
  • Вынести общие параметры (duration, triggerHook) в объекты или константы.
  • Разделять анимации на функции или timeline.
  • Управлять динамическим контентом через data-атрибуты.
  • Минимизировать дублирование кода и облегчать масштабирование страницы.

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