ScrollMagic — библиотека для создания анимаций при скролле, которая
требует аккуратной организации кода для поддерживаемости и
расширяемости. Ключевой принцип — разделение логики и
конфигурации сцен. Любая сцена в ScrollMagic строится вокруг
трех элементов: контроллера (ScrollMagic.Controller), сцены
(ScrollMagic.Scene) и триггерных элементов
(triggerElement).
Пример базовой структуры сцены:
// Создание контроллера
const controller = new ScrollMagic.Controller();
// Настройка сцены
const scene = new ScrollMagic.Scene({
triggerElement: "#section1",
duration: 500,
triggerHook: 0.5
})
.setClassToggle("#section1", "active")
.addTo(controller);
В этом примере видны три ключевых параметра сцены:
triggerElement (элемент, который запускает сцену),
duration (продолжительность действия сцены) и
triggerHook (позиция триггера относительно окна
просмотра).
При работе с большим проектом рекомендуется разбивать код на модули по типу анимаций или по страницам. Для этого можно использовать ES6-модули:
// scrollController.js
export const controller = new ScrollMagic.Controller();
// scenes/scene1.js
import { controller } from '../scrollController.js';
export function initScene1() {
new ScrollMagic.Scene({
triggerElement: "#section1",
duration: 400
})
.setTween("#section1", {opacity: 1, y: -50})
.addTo(controller);
}
Такой подход упрощает поддержку, особенно если анимаций становится десятки.
Для динамически создаваемых блоков удобно использовать фабрику сцен — функцию, которая создает сцену на основе конфигурации:
function createScene({trigger, target, duration, className}) {
return new ScrollMagic.Scene({
triggerElement: trigger,
duration: duration
})
.setClassToggle(target, className)
.addTo(controller);
}
// Применение
const scenes = [
{trigger: "#sec1", target: "#sec1", duration: 300, className: "visible"},
{trigger: "#sec2", target: "#sec2", duration: 400, className: "visible"}
];
scenes.forEach(cfg => createScene(cfg));
Такой паттерн уменьшает дублирование кода и позволяет централизованно управлять параметрами анимации.
ScrollMagic тесно интегрируется с GSAP, что позволяет создавать сложные временные анимации. Для чистой архитектуры стоит отделять определение анимаций от создания сцен:
import { gsap } from "gsap";
// Определение анимации
function animateSection(target) {
return gsap.fromTo(target, {opacity: 0, y: 50}, {opacity: 1, y: 0, duration: 1});
}
// Создание сцены
new ScrollMagic.Scene({
triggerElement: "#section3",
duration: 500
})
.setTween(animateSection("#section3"))
.addTo(controller);
Такой подход делает код более читаемым и позволяет тестировать анимации отдельно от сцен ScrollMagic.
Для сложных интерактивных эффектов используется подписка на события сцен:
enter — когда сцена активируетсяleave — когда сцена деактивируетсяupdate — при каждом обновлении позиции скроллаscene.on("enter", () => {
console.log("Сцена активирована");
})
.on("leave", () => {
console.log("Сцена покинута");
});
События можно использовать для запуска сторонних функций, изменения состояния UI или управления несколькими сценами одновременно.
Для проектов с множеством страниц часто создают один
глобальный контроллер, который импортируется во все модули. Это
упрощает синхронизацию сцен и позволяет использовать общий
refresh() при изменении DOM:
// main.js
import { controller } from './scrollController.js';
import { initScene1 } from './scenes/scene1.js';
import { initScene2 } from './scenes/scene2.js';
initScene1();
initScene2();
// Обновление контроллера после динамической загрузки контента
window.addEventListener('resize', () => controller.update());
scrollController.js — создание и экспорт одного
контроллераscenes/ — отдельные файлы для каждой сцены или группы
связанных сценanimations/ — функции анимаций, которые возвращают
GSAP-твиныutils/scrollHelpers.js — вспомогательные функции для
триггеров, проверок видимости и debounceДля крупных проектов удобно держать сцены в JSON-конфигурациях, которые затем превращаются в объекты сцен через фабрику:
const sceneConfigs = [
{trigger: "#sec1", target: "#sec1", duration: 300, animation: {opacity: 1, y: -50}},
{trigger: "#sec2", target: "#sec2", duration: 400, animation: {opacity: 1, scale: 1}}
];
sceneConfigs.forEach(cfg => {
const tween = gsap.to(cfg.target, cfg.animation);
new ScrollMagic.Scene({
triggerElement: cfg.trigger,
duration: cfg.duration
})
.setTween(tween)
.addTo(controller);
});
Такой подход позволяет легко изменять анимации без изменения основного кода и облегчает генерацию сцен на лету.
Эти паттерны обеспечивают поддерживаемый, расширяемый и понятный код при работе с большим количеством скролл-анимаций на сайте.