ScrollTrigger и Locomotive Scroll

Для интеграции Locomotive Scroll с GSAP ScrollTrigger необходимо сначала подключить обе библиотеки. Locomotive Scroll обеспечивает плавный скролл с контролем положения элементов, а ScrollTrigger отвечает за триггеры анимаций при прокрутке.

import LocomotiveScroll from "locomotive-scroll";
import { gsap } from "gsap";
import { ScrollTrigger } from "gsap/ScrollTrigger";

gsap.registerPlugin(ScrollTrigger);

const scrollContainer = document.querySelector("#scroll-container");

const locoScroll = new LocomotiveScroll({
  el: scrollContainer,
  smooth: true,
  multiplier: 1.2,
});

Ключевой момент: Locomotive Scroll использует виртуальный скролл. Это значит, что фактический скролл браузера скрыт, и нужно синхронизировать его с ScrollTrigger через специальный прокси.


Синхронизация Locomotive Scroll и ScrollTrigger

Чтобы ScrollTrigger корректно отслеживал положение элементов, необходимо настроить scrollerProxy:

locoScroll.on("scroll", ScrollTrigger.update);

ScrollTrigger.scrollerProxy(scrollContainer, {
  scrollTop(value) {
    return arguments.length ? locoScroll.scrollTo(value, 0, 0) : locoScroll.scroll.instance.scroll.y;
  },
  getBoundingClientRect() {
    return { top: 0, left: 0, width: window.innerWidth, height: window.innerHeight };
  },
  pinType: scrollContainer.style.transform ? "transform" : "fixed"
});

ScrollTrigger.addEventListener("refresh", () => locoScroll.update());
ScrollTrigger.refresh();

Важно:

  • scrollTop используется для получения и установки текущей позиции скролла.
  • getBoundingClientRect сообщает ScrollTrigger размеры контейнера.
  • pinType определяет метод закрепления (pin) элементов в зависимости от трансформаций Locomotive Scroll.

Создание анимаций с ScrollTrigger

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

gsap.from(".animate-item", {
  y: 100,
  opacity: 0,
  duration: 1,
  scrollTrigger: {
    trigger: ".animate-item",
    scroller: scrollContainer,
    start: "top 80%",
    end: "bottom 20%",
    scrub: true,
  }
});

Ключевые свойства ScrollTrigger:

  • trigger — элемент, при появлении которого запускается анимация.
  • scroller — контейнер Locomotive Scroll.
  • start и end — позиции начала и конца триггера относительно viewport.
  • scrub — синхронизация анимации с прокруткой, создавая эффект плавного скролла.

Использование pin с Locomotive Scroll

Pinning элементов при плавном скролле работает иначе, чем с обычным скроллом. Важно всегда указывать scroller и правильно выбирать pinType.

gsap.to(".pinned-section", {
  scrollTrigger: {
    trigger: ".pinned-section",
    scroller: scrollContainer,
    start: "top top",
    end: "+=500",
    pin: true,
    pinSpacing: true,
  },
  opacity: 1,
  duration: 1
});

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

  • pinSpacing: true сохраняет место для закрепленного элемента.
  • Пин работает через CSS transform для контейнеров с Locomotive Scroll.

Анимации параллакса

Для создания параллакс-эффекта с Locomotive Scroll используют синхронизацию с ScrollTrigger и разные значения смещения элементов:

gsap.to(".parallax-item", {
  y: -200,
  ease: "none",
  scrollTrigger: {
    trigger: ".parallax-section",
    scroller: scrollContainer,
    start: "top bottom",
    end: "bottom top",
    scrub: true,
  }
});

Примечание: scrub: true обеспечивает плавное движение параллакса вместе с прокруткой.


Работа с горизонтальным скроллом

Locomotive Scroll поддерживает горизонтальный скролл, что можно использовать для нестандартных интерфейсов. Пример настройки:

const locoScrollHorizontal = new LocomotiveScroll({
  el: document.querySelector(".horizontal-scroll"),
  smooth: true,
  direction: "horizontal",
});

ScrollTrigger.scrollerProxy(".horizontal-scroll", {
  scrollLeft(value) {
    return arguments.length ? locoScrollHorizontal.scrollTo(value, 0, 0) : locoScrollHorizontal.scroll.instance.scroll.x;
  },
  getBoundingClientRect() {
    return { top: 0, left: 0, width: window.innerWidth, height: window.innerHeight };
  },
  pinType: "transform"
});

Анимации привязываются к горизонтальной прокрутке так же, как и к вертикальной, но используют x вместо y.


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

  1. Использовать scrub: true только для ключевых анимаций, избегая массового вычисления на каждый кадр.
  2. Минимизировать количество pinned элементов, особенно на мобильных устройствах.
  3. Обновлять Locomotive Scroll при изменении размеров окна (resize) и динамическом контенте.
window.addEventListener("resize", () => {
  locoScroll.update();
  ScrollTrigger.refresh();
});

Советы по отладке

  • Если анимации не запускаются, проверить правильность выбора scroller.
  • Для мобильных устройств иногда требуется отключать smooth или уменьшать multiplier.
  • Использовать ScrollTrigger.refresh() после динамического добавления контента для корректного расчета триггеров.

Эти методы позволяют создавать сложные, отзывчивые анимации на основе Locomotive Scroll и ScrollTrigger, включая параллакс, pinned-секции и горизонтальный скролл, при этом обеспечивая высокую производительность и плавность интерфейса.