Процедурная анимация

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

Контроллер и сцены

Контроллер (ScrollMagic.Controller) — это объект, который управляет всеми сценами на странице. Он отслеживает положение скролла и передает его каждой сцене для вычисления прогресса анимации.

const controller = new ScrollMagic.Controller();

Сцена (ScrollMagic.Scene) описывает участок страницы, на котором будет происходить анимация. Основные параметры сцены:

  • triggerElement — элемент, относительно которого начинается сцена.
  • duration — длина сцены в пикселях (или в процентах от окна).
  • offset — смещение от начала триггерного элемента.
  • triggerHook — точка на экране, где начинается сцена (0 — верх, 1 — низ, 0.5 — середина).

Пример создания сцены:

const scene = new ScrollMagic.Scene({
  triggerElement: "#section1",
  duration: 500,
  triggerHook: 0.5
});
scene.addTo(controller);

Анимация с помощью GSAP

ScrollMagic тесно интегрируется с библиотекой GSAP, что позволяет создавать сложные, плавные анимации элементов. Для процедурной анимации часто используют TweenMax или gsap.to().

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

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

В этом примере анимация элемента #box привязана к позиции скролла. При прокрутке сцены элемент постепенно смещается на 300px и вращается на 360°.

Контроль прогресса анимации

Процедурная анимация часто требует динамического управления прогрессом. ScrollMagic позволяет это через события progress, enter, leave:

scene.on("progress", function(event) {
  console.log("Прогресс сцены:", event.progress);
});
scene.on("enter", function() {
  console.log("Сцена активирована");
});
scene.on("leave", function() {
  console.log("Сцена завершена");
});

event.progress возвращает число от 0 до 1, которое отражает, насколько пользователь прокрутил сцену. Это удобно для изменения стилей или запуска пользовательских функций.

Параллакс-эффекты

Процедурная анимация в ScrollMagic часто используется для создания параллакса — движения слоев с разной скоростью относительно скролла. Для этого создаются сцены с разными duration и triggerHook:

gsap.to("#background", {y: -100, ease: "none"});
gsap.to("#foreground", {y: -200, ease: "none"});

const sceneBackground = new ScrollMagic.Scene({
  triggerElement: "#section2",
  duration: 1000
}).setTween("#background", {y: -100, ease: "none"}).addTo(controller);

const sceneForeground = new ScrollMagic.Scene({
  triggerElement: "#section2",
  duration: 1000
}).setTween("#foreground", {y: -200, ease: "none"}).addTo(controller);

Элементы перемещаются с разной скоростью, создавая эффект глубины.

Логика процедурной анимации

В отличие от заранее заданных анимаций, процедурная анимация реагирует на текущий прогресс сцены. Это означает, что анимация может меняться в зависимости от положения скролла или других условий. Примеры:

  1. Изменение прозрачности элемента по мере прокрутки:
scene.on("progress", function(event) {
  gsap.to("#fadeElement", {opacity: event.progress});
});
  1. Масштабирование и вращение с комбинированными эффектами:
scene.on("progress", function(event) {
  gsap.to("#dynamicBox", {
    scale: 1 + event.progress,
    rotation: 360 * event.progress
  });
});
  1. Управление несколькими свойствами одновременно:
scene.on("progress", function(event) {
  const progress = event.progress;
  gsap.to("#complexElement", {
    x: 200 * progress,
    y: 100 * progress,
    opacity: progress
  });
});

Привязка к пользовательскому взаимодействию

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

document.querySelector("#startBtn").addEventListener("click", () => {
  controller.update(true);
});

Советы по оптимизации

  • Использовать transform вместо top/left для плавных GPU-ускоренных анимаций.
  • Ограничивать количество сцен и анимаций на странице, чтобы избежать тормозов.
  • Выносить сложные вычисления прогресса в отдельные функции.
  • Комбинировать ScrollMagic с GSAP для синхронизации нескольких свойств одновременно.

Практическая структура кода

Для больших проектов рекомендуется структурировать код следующим образом:

// Создание контроллера
const controller = new ScrollMagic.Controller();

// Определение сцен
const scenes = [
  {
    trigger: "#section1",
    duration: 500,
    tweenProps: {x: 300, rotation: 360}
  },
  {
    trigger: "#section2",
    duration: 1000,
    tweenProps: {y: -200, opacity: 1}
  }
];

// Инициализация сцен
scenes.forEach(sceneConfig => {
  const tween = gsap.to(sceneConfig.trigger, sceneConfig.tweenProps);
  new ScrollMagic.Scene({
    triggerElement: sceneConfig.trigger,
    duration: sceneConfig.duration
  }).setTween(tween).addTo(controller);
});

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