Управление фокусом

В контексте ScrollMagic под «фокусом» понимается управление вниманием пользователя через изменение состояния элементов в зависимости от положения скролла. Это достигается с помощью сцен (Scene), контроллера (Controller) и привязки к триггерам. Грамотное управление фокусом позволяет:

  • выделять активные секции страницы;
  • управлять состояниями интерфейса (активные пункты меню, подсветка блоков);
  • синхронизировать анимации с текущей позицией прокрутки;
  • создавать эффект «погружения» при скроллинге.

Контроллер как центр управления

ScrollMagic строится вокруг объекта Controller, который отслеживает прокрутку и обновляет связанные сцены.

const controller = new ScrollMagic.Controller();

Контроллер может быть настроен:

  • container — элемент с прокруткой (по умолчанию window);
  • globalSceneOptions — общие настройки для всех сцен;
  • loglevel — уровень логирования (0–3).

Пример:

const controller = new ScrollMagic.Controller({
  globalSceneOptions: {
    triggerHook: 0.5
  }
});

Это задаёт центральную точку экрана как базовый ориентир для всех сцен.

Триггеры и зона фокуса

Ключевым элементом является triggerElement — DOM-элемент, при достижении которого сцена активируется.

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

Параметры:

  • triggerElement — элемент, определяющий момент активации;
  • triggerHook — положение на экране (0 — верх, 1 — низ);
  • duration — длина сцены в пикселях.

Фокус формируется внутри диапазона duration. Пока пользователь находится в этом диапазоне, сцена считается активной.

Состояния сцены

Каждая сцена имеет три состояния:

  • BEFORE — до начала сцены;
  • DURING — внутри диапазона;
  • AFTER — после завершения.

Отслеживание состояния:

scene.on('enter', () => {
  console.log('Вошли в сцену');
});

scene.on('leave', () => {
  console.log('Покинули сцену');
});

Использование этих событий позволяет управлять фокусом — например, менять классы элементов.

Подсветка активных секций

Классический пример управления фокусом — подсветка текущего блока страницы.

document.querySelectorAll('.section').forEach(section => {
  new ScrollMagic.Scene({
    triggerElement: section,
    triggerHook: 0.5,
    duration: section.offsetHeight
  })
  .setClassToggle(section, 'active')
  .addTo(controller);
});

Здесь:

  • при попадании секции в центр экрана она получает класс active;
  • класс снимается при выходе из зоны.

Синхронизация с навигацией

Управление фокусом часто используется для синхронизации с меню.

document.querySelectorAll('.section').forEach((section, index) => {
  const navItem = document.querySelectorAll('.nav-item')[index];

  new ScrollMagic.Scene({
    triggerElement: section,
    triggerHook: 0.3,
    duration: section.offsetHeight
  })
  .on('enter', () => navItem.classList.add('active'))
  .on('leave', () => navItem.classList.remove('active'))
  .addTo(controller);
});

Особенности:

  • triggerHook: 0.3 смещает точку активации выше центра;
  • навигация отражает текущий фокус пользователя.

Закрепление элементов (Pinning)

Закрепление — один из способов усилить фокус на элементе.

new ScrollMagic.Scene({
  triggerElement: '#pin-block',
  duration: 500
})
.setPin('#pin-block')
.addTo(controller);

Поведение:

  • элемент «прилипает» к экрану;
  • остаётся на месте, пока не закончится duration.

Это создаёт эффект концентрации внимания на контенте.

Плавное изменение состояния

Фокус можно управлять не только бинарно (активен/неактивен), но и плавно, через прогресс сцены.

scene.on('progress', event => {
  const progress = event.progress;
  document.querySelector('#box').style.opacity = progress;
});

progress изменяется от 0 до 1, что позволяет:

  • плавно изменять прозрачность;
  • масштаб;
  • позицию;
  • цвет.

Управление несколькими зонами фокуса

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

const scenes = [];

document.querySelectorAll('.step').forEach(step => {
  const scene = new ScrollMagic.Scene({
    triggerElement: step,
    triggerHook: 0.5,
    duration: 200
  })
  .setClassToggle(step, 'focused')
  .addTo(controller);

  scenes.push(scene);
});

Подход:

  • каждая сцена отвечает за свой элемент;
  • фокус переключается по мере прокрутки;
  • возможно наложение состояний.

Работа с вложенными контейнерами

Если прокрутка происходит внутри контейнера:

const container = document.querySelector('.scroll-container');

const controller = new ScrollMagic.Controller({
  container: container
});

Важно:

  • все triggerElement должны находиться внутри контейнера;
  • координаты рассчитываются относительно контейнера, а не окна.

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

Управление фокусом может быть ресурсоёмким при большом количестве сцен. Рекомендации:

  • минимизировать количество активных сцен;
  • использовать reverse: false, если не требуется обратное проигрывание:
new ScrollMagic.Scene({
  triggerElement: '#block',
  reverse: false
});
  • объединять логику, избегая дублирования;
  • отключать сцены вне области видимости.

Отладка и визуализация

Для контроля зон фокуса используется плагин debug.addIndicators.

scene.addIndicators({
  name: 'Focus Zone',
  colorStart: 'green',
  colorEnd: 'red'
});

Отображает:

  • точку триггера;
  • начало и конец сцены;
  • текущую позицию.

Это позволяет точно настраивать поведение фокуса.

Интеграция с GSAP

ScrollMagic часто используется вместе с GSAP для более гибкого управления анимациями.

const tween = gsap.to('#box', {
  scale: 1.5,
  duration: 1
});

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

В этом случае:

  • фокус управляет анимацией;
  • анимация синхронизирована с прокруткой.

Динамическое обновление сцен

При изменении DOM необходимо обновлять сцены:

controller.update(true);

Или:

scene.refresh();

Это важно при:

  • загрузке изображений;
  • изменении размеров элементов;
  • динамическом добавлении контента.

Композиция сложных сценариев

Для сложных страниц управление фокусом строится как композиция:

  • базовые сцены для секций;
  • дополнительные сцены для анимаций;
  • сцены для закрепления элементов;
  • сцены для синхронизации UI.

Такая архитектура позволяет:

  • изолировать логику;
  • легко масштабировать;
  • избегать конфликтов между сценами.