Синхронизация с прокруткой

Синхронизация в Locomotive Scroll строится на привязке поведения элементов к текущей позиции скролла. Библиотека перехватывает стандартную прокрутку, создаёт виртуальную систему координат и обновляет состояние элементов при каждом изменении положения.

Ключевой механизм — отслеживание позиции контейнера и вычисление относительного положения каждого элемента с атрибутами data-scroll.


Базовая архитектура синхронизации

При инициализации создаётся экземпляр:

const scroll = new LocomotiveScroll({
  el: document.querySelector('[data-scroll-container]'),
  smooth: true
});

После этого:

  • контейнер становится источником прокрутки
  • элементы с data-scroll регистрируются во внутренней системе
  • каждый кадр пересчитывается их положение

Синхронизация достигается через:

  • позицию скролла (scroll.y)
  • границы элементов
  • смещение относительно viewport

Атрибуты управления синхронизацией

data-scroll

Активирует элемент в системе наблюдения.

<div data-scroll></div>

data-scroll-speed

Определяет скорость движения элемента относительно прокрутки.

<div data-scroll data-scroll-speed="2"></div>
  • 1 — стандартная скорость
  • >1 — ускорение (параллакс)
  • <1 — замедление

data-scroll-direction

Задаёт направление смещения:

<div data-scroll data-scroll-speed="1" data-scroll-direction="horizontal"></div>

Возможные значения:

  • vertical (по умолчанию)
  • horizontal

Событие scroll и синхронизация логики

Locomotive Scroll предоставляет событие scroll, позволяющее синхронизировать пользовательскую логику:

scroll.on('scroll', (args) => {
  console.log(args.scroll.y);
});

Объект args содержит:

  • scroll.x, scroll.y — текущая позиция
  • limit — границы прокрутки
  • direction — направление
  • speed — скорость прокрутки

Пример синхронизации анимации:

scroll.on('scroll', ({ scroll }) => {
  const opacity = scroll.y / 500;
  document.querySelector('.box').style.opacity = opacity;
});

Синхронизация через data-scroll-call

Позволяет вызывать события при попадании элемента в область видимости.

<div data-scroll data-scroll-call="animateBox"></div>

Обработка:

scroll.on('call', (value, way, obj) => {
  if (value === 'animateBox' && way === 'enter') {
    obj.el.classList.add('active');
  }
});

Параметры:

  • value — имя события
  • wayenter или leave
  • obj.el — DOM-элемент

Контроль позиции элемента

Каждый элемент имеет внутренние параметры:

  • top — верхняя граница
  • bottom — нижняя граница
  • progress — процент прохождения viewport

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

scroll.on('scroll', (args) => {
  args.currentElements['my-element-id']?.progress;
});

HTML:

<div 
  data-scroll 
  data-scroll-id="my-element-id">
</div>

progress изменяется от 0 до 1:

  • 0 — элемент только появился
  • 1 — полностью прошёл экран

Пример:

scroll.on('scroll', (args) => {
  const el = args.currentElements['my-element-id'];
  
  if (el) {
    const scale = 1 + el.progress;
    el.el.style.transform = `scale(${scale})`;
  }
});

Синхронизация с CSS-классами

Библиотека автоматически добавляет классы:

  • is-inview — элемент в зоне видимости
  • has-scroll-scrolling — идёт прокрутка
  • has-scroll-smooth — включён smooth режим

Пример:

[data-scroll] {
  opacity: 0;
  transition: opacity 0.6s;
}

[data-scroll].is-inview {
  opacity: 1;
}

Это позволяет синхронизировать визуальные эффекты без JavaScript.


Секция data-scroll-section

Оптимизация синхронизации достигается разделением контента:

<section data-scroll-section>
  <div data-scroll></div>
</section>

Каждая секция:

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

Смещение и триггеры

data-scroll-offset

Определяет момент срабатывания:

<div data-scroll data-scroll-offset="100,50"></div>

Формат:

"topOffset,bottomOffset"
  • первое значение — отступ сверху
  • второе — снизу

Плавная синхронизация и lerp

Параметр lerp управляет плавностью:

const scroll = new LocomotiveScroll({
  smooth: true,
  lerp: 0.1
});
  • 0 — резкое движение
  • 0.1–0.2 — плавная инерция
  • >0.3 — сильное сглаживание

Синхронизация зависит от этого параметра:

  • при высоком lerp события запаздывают
  • при низком — точнее соответствуют позиции

Ручная синхронизация через update

При динамических изменениях DOM:

scroll.update();

Используется после:

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

Без вызова update синхронизация нарушается.


Программная прокрутка

Метод scrollTo позволяет синхронизировать переходы:

scroll.scrollTo('#section', {
  offset: -100,
  duration: 800
});

Параметры:

  • offset — дополнительное смещение
  • duration — длительность
  • easing — функция сглаживания

Горизонтальная синхронизация

Для горизонтальных эффектов:

const scroll = new LocomotiveScroll({
  el: container,
  direction: 'horizontal'
});

Синхронизация работает аналогично, но через scroll.x.


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

Для сложных сценариев:

function raf() {
  scroll.update();
  requestAnimationFrame(raf);
}

raf();

Позволяет:

  • синхронизировать с кастомными рендерами
  • объединять с WebGL или Canvas

Типичные проблемы синхронизации

1. Несоответствие позиций

  • забытый data-scroll-container
  • неправильная структура DOM

2. Дёргание анимаций

  • слишком высокий lerp
  • тяжёлые вычисления в scroll обработчике

3. Элементы не реагируют

  • отсутствует data-scroll
  • не вызван update()

Практический пример синхронизации

<div data-scroll-container>
  <section data-scroll-section>
    <div 
      data-scroll 
      data-scroll-speed="2"
      data-scroll-id="box">
    </div>
  </section>
</div>
scroll.on('scroll', (args) => {
  const box = args.currentElements['box'];

  if (box) {
    const rotate = box.progress * 360;
    box.el.style.transform = `rotate(${rotate}deg)`;
  }
});

В этом примере:

  • прокрутка управляет вращением
  • используется progress
  • достигается полная синхронизация анимации и скролла