В работе с библиотекой ScrollMagic часто возникают задачи, связанные с обработкой событий прокрутки. Одной из особенностей таких событий является их высокая частота — браузер может генерировать десятки или сотни событий в секунду при плавной прокрутке страницы. Если на каждое событие выполнять сложные вычисления или анимации, это приведёт к торможению страницы и падению производительности. Для решения этой проблемы используются методы throttle и debounce.
throttle от
debounceThrottle и debounce решают схожую задачу — контроль частоты вызова функции, но делают это по-разному:
Throttle Ограничивает вызов функции до одного
раза за фиксированный интервал времени. Пример: если
throttle установлен на 200 мс, функция будет вызываться
максимум раз в 200 мс, независимо от того, сколько событий
произошло.
Когда использовать:
Debounce Вызывает функцию только после того, как событие перестало происходить в течение заданного времени. Пример: если задержка debounce 300 мс, функция сработает только спустя 300 мс после последнего события прокрутки.
Когда использовать:
ScrollMagic использует события прокрутки для управления анимациями через Scene и Controller. Часто возникает ситуация, когда необходимо оптимизировать обработчики, например, для анимации объектов при скролле.
// Подключение ScrollMagic
const controller = new ScrollMagic.Controller();
// Пример функции для анимации
function animateElement() {
console.log('Анимация сработала');
}
// Debounce-функция
function debounce(func, wait) {
let timeout;
return function(...args) {
clearTimeout(timeout);
timeout = setTimeout(() => func.apply(this, args), wait);
};
}
// Throttle-функция
function throttle(func, limit) {
let lastFunc;
let lastRan;
return function(...args) {
const context = this;
if (!lastRan) {
func.apply(context, args);
lastRan = Date.now();
} else {
clearTimeout(lastFunc);
lastFunc = setTimeout(function() {
if ((Date.now() - lastRan) >= limit) {
func.apply(context, args);
lastRan = Date.now();
}
}, limit - (Date.now() - lastRan));
}
};
}
// Создание сцены ScrollMagic
const scene = new ScrollMagic.Scene({
triggerElement: '#trigger',
duration: 500
})
.addTo(controller);
// Применение throttle к событию update
scene.on('update', throttle(animateElement, 100));
В этом примере:
animateElement будет вызываться не чаще одного раза в
100 мс, даже если события update происходят чаще.| Параметр | Throttle | Debounce |
|---|---|---|
| Частота вызова | Постоянная в заданный интервал | Только после остановки событий |
| Идеальный сценарий | Анимации при прокрутке | Подгрузка данных, расчет позиций |
| Влияние на UI | Обеспечивает плавную, но ограниченную реакцию | Функция срабатывает один раз после паузы |
ScrollMagic часто используется вместе с GSAP для
анимаций. При комбинировании важно оборачивать тяжелые анимационные
функции через throttle:
scene.on('update', throttle(() => {
gsap.to('#box', {x: window.scrollY, duration: 0.5});
}, 50));
Такой подход гарантирует плавность движения элементов без перегрузки рендеринга.
throttle и debounce можно создавать
вручную (как показано выше) или использовать готовые реализации из
Lodash (_.throttle,
_.debounce).update,
enter, leave, и все они могут генерироваться
очень часто, поэтому без контроля частоты вызовов возможны тормоза.