Ленивая загрузка сцен

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


Инициализация ScrollMagic Controller

Перед работой с ленивой загрузкой необходимо создать контроллер:

const controller = new ScrollMagic.Controller({
    globalSceneOptions: {
        triggerHook: 0.8
    }
});
  • triggerHook определяет, в какой точке экрана активируется сцена (от 0 до 1).
  • globalSceneOptions задаёт общие параметры для всех сцен.

Контроллер будет управлять всеми сценами на странице, включая лениво созданные.


Создание функции для ленивой загрузки сцены

Основная идея ленивой загрузки: сцена создаётся только перед её появлением в области видимости. Для этого используют событие scroll или Intersection Observer.

function createScene(selector, animation) {
    const element = document.querySelector(selector);
    if (!element) return null;

    return new ScrollMagic.Scene({
        triggerElement: element,
        duration: element.offsetHeight
    })
    .setTween(animation)
    .addTo(controller);
}
  • triggerElement — элемент, при достижении которого активируется сцена.
  • duration — длина сцены (может быть фиксированной или равной высоте элемента).
  • setTween(animation) связывает сцену с анимацией, созданной через GSAP или CSS-анимацию.

Использование Intersection Observer для ленивой загрузки

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

const observer = new IntersectionObserver((entries, observer) => {
    entries.forEach(entry => {
        if (entry.isIntersecting) {
            const animation = gsap.from(entry.target, { opacity: 0, y: 50, duration: 1 });
            createScene(`#${entry.target.id}`, animation);
            observer.unobserve(entry.target);
        }
    });
}, { threshold: 0.1 });

document.querySelectorAll('.lazy-scene').forEach(el => observer.observe(el));
  • threshold определяет долю видимой области элемента для срабатывания.
  • observer.unobserve(entry.target) отключает наблюдение после создания сцены, чтобы не расходовать ресурсы.

Управление большим количеством сцен

При большом числе элементов лучше не создавать все сцены сразу. Ленивый подход позволяет создавать сцены по мере прокрутки, а старые сцены можно удалять, освобождая память:

const scenes = [];

function lazyLoadScene(el) {
    const animation = gsap.from(el, { opacity: 0, y: 50, duration: 1 });
    const scene = createScene(`#${el.id}`, animation);
    scenes.push(scene);
}

function destroyOldScenes() {
    while (scenes.length > 50) {
        const oldScene = scenes.shift();
        oldScene.destroy(true);
    }
}

document.querySelectorAll('.lazy-scene').forEach(el => {
    lazyLoadScene(el);
    destroyOldScenes();
});
  • destroy(true) удаляет сцену и все связанные события.
  • Поддерживается ограничение на количество активных сцен, что полезно для страниц с длинной прокруткой.

Совмещение с динамическим контентом

Если элементы добавляются динамически (например, через AJAX или Infinite Scroll), ленивые сцены создаются при вставке в DOM:

function onNewContentAdded(container) {
    container.querySelectorAll('.lazy-scene').forEach(el => {
        const animation = gsap.from(el, { opacity: 0, y: 50, duration: 1 });
        createScene(`#${el.id}`, animation);
    });
}
  • Это гарантирует, что новые элементы будут анимированы только тогда, когда они появляются на странице.
  • Можно комбинировать с Intersection Observer для автоматического отслеживания новых элементов.

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

  1. Минимизация количества сцен: создаются только необходимые сцены.
  2. Удаление ненужных сцен: старые сцены уничтожаются методом destroy.
  3. Использование Intersection Observer: экономит ресурсы по сравнению с постоянным слушателем scroll.
  4. Делегирование анимаций: если несколько элементов имеют одинаковую анимацию, сцена может управлять их группой вместо отдельных сцен.

Пример полного ленивого цикла

const controller = new ScrollMagic.Controller();
const observer = new IntersectionObserver((entries, obs) => {
    entries.forEach(entry => {
        if (entry.isIntersecting) {
            const animation = gsap.from(entry.target, { opacity: 0, y: 50, duration: 1 });
            new ScrollMagic.Scene({
                triggerElement: entry.target,
                duration: entry.target.offsetHeight
            })
            .setTween(animation)
            .addTo(controller);

            obs.unobserve(entry.target);
        }
    });
}, { threshold: 0.1 });

document.querySelectorAll('.lazy-scene').forEach(el => observer.observe(el));
  • Эффективно создаёт сцены по мере прокрутки.
  • Не перегружает браузер множеством неактивных сцен.
  • Позволяет интегрировать динамический контент без переработки всей логики.

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