Waypoints — это библиотека JavaScript, которая позволяет отслеживать положение элементов на странице относительно видимой области браузера. В контексте SPA (Single Page Application) она особенно полезна для создания динамического поведения интерфейса при скролле, поскольку элементы страницы могут загружаться асинхронно и изменять своё положение без полной перезагрузки страницы.
Ключевые возможности:
В SPA важен правильный момент инициализации waypoint’ов, так как DOM может изменяться динамически. Обычно это делается после рендера компонента или загрузки контента.
// Пример базовой инициализации Waypoint
import Waypoint from 'waypoints/lib/noframework.waypoints';
const waypoint = new Waypoint({
element: document.getElementById('section1'),
handler: function(direction) {
console.log('Элемент достигнут, направление:', direction);
},
offset: '50%' // Триггер срабатывает, когда элемент находится в середине видимой области
});
Особенности в SPA:
offset для точного позиционированияПараметр offset определяет точку, в которой waypoint
срабатывает. В SPA часто встречаются следующие варианты:
'25%',
'50%', '75%'.200 (срабатывает, когда верх
элемента на 200px от верхнего края окна).const dynamicWaypoint = new Waypoint({
element: document.querySelector('.dynamic-section'),
handler: function(direction) {
console.log('Секция видна:', direction);
},
offset: function() {
return window.innerHeight * 0.3; // Триггер на 30% от высоты окна
}
});
SPA часто содержит несколько секций с различными действиями при скролле. Для этого можно использовать массивы waypoint’ов или создавать их программно в цикле.
document.querySelectorAll('.section').forEach((section) => {
new Waypoint({
element: section,
handler: function(direction) {
console.log('Секция:', section.id, 'напряжение:', direction);
},
offset: '75%'
});
});
Рекомендации:
destroy() для удаления waypoint после
срабатывания, если повторные триггеры не нужны.По умолчанию Waypoints отслеживает вертикальный скролл, но можно подключить горизонтальный, что актуально для SPA с горизонтальной прокруткой.
new Waypoint({
element: document.querySelector('.horizontal-section'),
handler: function(direction) {
console.log('Горизонтальная секция достигнута');
},
horizontal: true, // включение горизонтального скролла
offset: '50%'
});
В SPA часто элементы добавляются после первичного рендера страницы (lazy loading, асинхронные компоненты). В таких случаях waypoint’ы создаются после вставки элементов в DOM:
function initDynamicWaypoints() {
document.querySelectorAll('.lazy-loaded').forEach((el) => {
new Waypoint({
element: el,
handler: function(direction) {
el.classList.add('visible');
},
offset: '80%'
});
});
}
// Пример вызова после загрузки данных через fetch
fetch('/api/sections')
.then(res => res.json())
.then(data => {
renderSections(data); // вставка контента в DOM
initDynamicWaypoints(); // инициализация waypoint’ов
});
Совет: при удалении элементов из DOM следует также
вызывать destroy() для waypoint’ов, чтобы избежать утечек
памяти.
Для React, Vue или Angular важно создавать waypoint’ы в lifecycle-хуках:
useEffect после рендера
компонента.mounted() после вставки
элемента.ngAfterViewInit() после
рендера view.// React пример
import { useEffect } from 'react';
import Waypoint from 'waypoints/lib/noframework.waypoints';
function Section() {
useEffect(() => {
const waypoint = new Waypoint({
element: document.getElementById('section1'),
handler: function(direction) {
console.log('React-секция достигнута');
},
offset: '60%'
});
return () => waypoint.destroy();
}, []);
return <div id="section1">Контент</div>;
}
Waypoints идеально подходят для триггера анимаций и подгрузки изображений:
.animate при достижении элемента.new Waypoint({
element: document.querySelector('.animate-section'),
handler: function() {
this.element.classList.add('animate');
},
offset: '90%'
});
new Waypoint({
element: document.querySelector('img[data-src]'),
handler: function() {
const img = this.element;
img.src = img.dataset.src;
img.removeAttribute('data-src');
},
offset: '100%'
});
continuous: false, если не требуется
многократное срабатывание при небольших прокрутках.destroy().Waypoints позволяют реализовать:
const sections = document.querySelectorAll('.section');
sections.forEach(section => {
new Waypoint({
element: section,
handler: function(direction) {
document.querySelectorAll('.menu-item').forEach(item => item.classList.remove('active'));
document.querySelector(`.menu-item[href="#${section.id}"]`).classList.add('active');
},
offset: '50%'
});
});
Эта техника часто используется в SPA для поддержания интуитивного интерфейса с динамическими элементами и прокруткой без перезагрузки страницы.