В браузере текущая позиция прокрутки представляет собой числовое смещение страницы или контейнера относительно начального положения. Для окна браузера используются значения вертикального и горизонтального скролла, которые становятся основой для синхронизации анимаций, триггеров появления элементов и динамических эффектов.
В контексте Velocity.js работа с прокруткой обычно делится на два уровня: получение текущего значения scroll и использование этого значения как условия или параметра для анимации.
Для окна браузера наиболее распространённые источники данных:
const scrollTop = window.pageYOffset;
Альтернативный вариант с поддержкой старых браузеров:
const scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
Горизонтальная позиция:
const scrollLeft = window.pageXOffset;
Эти значения обновляются при каждом событии прокрутки и используются как опорная точка для логики интерфейса.
Событие прокрутки является основным механизмом отслеживания изменения позиции:
window.addEventListener('scroll', () => {
const scrollTop = window.pageYOffset;
});
При высокой частоте вызовов важно учитывать производительность, так как scroll генерирует большое количество событий в секунду. В подобных случаях часто применяется throttling или requestAnimationFrame.
Velocity.js предоставляет встроенную поддержку анимации прокрутки
через специальную команду scroll.
Базовый пример плавной прокрутки к элементу:
Velocity(document.body, "scroll", {
duration: 800,
offset: -100,
easing: "easeInOutQuart"
});
Параметр offset позволяет скорректировать финальную
позицию, например, для учёта фиксированной шапки интерфейса.
Scroll-позиция часто используется не для самой прокрутки, а для вычисления состояния интерфейса:
const scrollTop = window.pageYOffset;
if (scrollTop > 300) {
Velocity(element, { opacity: 1, translateY: 0 }, { duration: 300 });
} else {
Velocity(element, { opacity: 0, translateY: 20 }, { duration: 300 });
}
Такой подход позволяет связывать появление элементов с глубиной прокрутки.
Для минимизации нагрузки scroll-события часто заменяются циклом анимации:
function update() {
const scrollTop = window.pageYOffset;
element.style.transform = `translateY(${scrollTop * 0.2}px)`;
requestAnimationFrame(update);
}
update();
Хотя сам Velocity.js не требует такого подхода для базовых анимаций, подобная схема используется при сложных интерфейсах с параллакс-эффектами.
Параллакс-эффект формируется за счёт разной скорости движения слоёв относительно scrollTop:
window.addEventListener('scroll', () => {
const scrollTop = window.pageYOffset;
Velocity(background, {
translateY: scrollTop * 0.3
}, {
duration: 0
});
Velocity(foreground, {
translateY: scrollTop * 0.6
}, {
duration: 0
});
});
Здесь скорость движения задаётся коэффициентом, связанным с текущей позицией прокрутки.
Если прокрутка происходит внутри блока, используется свойство
scrollTop самого элемента:
const container = document.querySelector('.scroll-container');
container.addEventListener('scroll', () => {
const position = container.scrollTop;
});
В таких сценариях Velocity работает с тем же принципом, но анимация применяется к конкретному DOM-элементу вместо окна.
Часто scroll нормализуется в диапазон от 0 до 1:
const maxScroll = document.body.scrollHeight - window.innerHeight;
const progress = window.pageYOffset / maxScroll;
Это значение удобно использовать для управления параметрами анимации:
Velocity(element, {
opacity: progress,
scale: 0.5 + progress * 0.5
}, {
duration: 0
});
Scroll-позиция часто применяется для построения систем состояний интерфейса:
window.addEventListener('scroll', () => {
const scrollTop = window.pageYOffset;
switch (true) {
case scrollTop < 200:
Velocity(header, { height: "120px" }, { duration: 300 });
break;
case scrollTop < 600:
Velocity(header, { height: "80px" }, { duration: 300 });
break;
default:
Velocity(header, { height: "60px" }, { duration: 300 });
}
});
Такой подход позволяет строить адаптивные интерфейсы, реагирующие на глубину просмотра страницы.
Velocity.js использует очередь анимаций, что позволяет связывать прокрутку с последовательными эффектами:
Velocity(element, "scroll", {
duration: 600
}).then(() => {
Velocity(element, { opacity: 1 }, { duration: 300 });
});
Так формируется цепочка: сначала изменение позиции, затем визуальный эффект.
При программной прокрутке возможно резкое изменение scrollTop, которое влияет на интерфейс. Для стабилизации используется фильтрация:
let lastScroll = 0;
window.addEventListener('scroll', () => {
const current = window.pageYOffset;
const delta = current - lastScroll;
if (Math.abs(delta) > 50) {
Velocity(element, { translateY: delta }, { duration: 200 });
}
lastScroll = current;
});
Фиксированные элементы часто меняют состояние в зависимости от позиции:
window.addEventListener('scroll', () => {
const scrollTop = window.pageYOffset;
Velocity(navbar, {
boxShadow: scrollTop > 100 ? "0 2px 10px rgba(0,0,0,0.2)" : "none"
}, {
duration: 200
});
});
Анимации, запускаемые при достижении определённой позиции:
window.addEventListener('scroll', () => {
const scrollTop = window.pageYOffset;
if (scrollTop > section.offsetTop - window.innerHeight / 2) {
Velocity(section, { opacity: 1, translateY: 0 }, { duration: 500 });
}
});
Подобные конструкции часто используются для постепенного раскрытия контента при прокрутке.