Удалите функции тайм-аута и избавьтесь от ошибок. Вот событие, которое вам действительно нужно: scrollend.
До появления события scrollend не было надежного способа определить, что прокрутка завершена. Это означало, что события срабатывали с задержкой или когда палец пользователя все ещё касался экрана. Из-за этого возникали ошибки и неудобства для пользователей.
document.onscroll = event => { clearTimeout(window.scrollEndTimer) window.scrollEndTimer = setTimeout(callback, 100) }
Лучшее, что может сделать эта стратегия setTimeout(), – определить, что прокрутка остановилась на 100ms. Это делает его больше похожим на событие приостановки прокрутки, а не на событие ее завершения.
После события scrollend браузер выполняет все эти сложные вычисления за вас.
document.onscrollend = event => {…}
Это то, что нужно. Они отправляются в нужный момент и содержат все необходимые условия.
Попробовать
Сведения о трансляции
Событие scrollend срабатывает, когда:
- браузер больше не анимирует и не преобразует прокрутку;
- Пользователь убрал палец с экрана.
- Пользователь отпустил бегунок прокрутки.
- Клавиша отпущена.
- Прокрутка до фрагмента завершена.
– Привязка прокрутки завершена.
- scrollTo() has completed.
- Пользователь прокрутил область просмотра.
Событие scrollend не активируется, если:
- Жест пользователя не привел к изменению положения прокрутки (перемещение не произошло).
- scrollTo() не привело к переводу.
Одна из причин, по которой это событие так долго не появлялось на веб-платформе, заключалась в том, что многие мелкие детали требовали уточнения. Одной из самых сложных областей
было формулирование деталей scrollend для Visual Viewport
по сравнению с документом. Представьте, что вы увеличиваете масштаб веб-страницы. Вы можете прокручивать экран в этом увеличенном состоянии, и это не обязательно будет прокрутка документа. Даже при такой прокрутке, выполняемой пользователем, после ее завершения будет сгенерировано событие scrollend.
Использование события
Как и в случае с другими событиями прокрутки, вы можете зарегистрировать прослушиватели несколькими способами.
addEventListener("scrollend",> (event) = {
// scroll ended
});
aScrollingElement.addEventListener("scroll>end", (event) = {
// scroll ended
});
или используйте свойство события:
document.onscrollend = (event) => {
// scroll ended
};
aScrollingElement.onscrollend = (event) => {
// scroll ended
};
Полифилы и прогрессивное улучшение
Если вы хотите использовать новое событие уже сейчас, ознакомьтесь с нашими рекомендациями. Вы можете продолжать использовать текущую стратегию завершения прокрутки (если она у вас есть) и в начале ее проверять поддержку с помощью:
'onscrollend' in window
// true, if available
В зависимости от того, поддерживает ли браузер событие, будет возвращено значение true или false. С помощью этой проверки вы можете разветвить код:
if ('onscrollend' in window) {
document.onscrollend = callback
}
else {
document.onscroll => event = {
clearTimeout(window.scrollEndTimer)
window.scrollEndTimer = setTimeout(callback, 100)
}
}
Это хорошее начало для постепенного улучшения события scrollend, когда оно станет доступно. Вы также можете попробовать
полифил
(NPM), который я создал,
чтобы браузер мог:
import {scrollend} from "scrollyfills"
// then use scrollend as if it's existed this whole time
document.onscrollend = callback
Полифил будет использовать прогрессивное улучшение, чтобы использовать встроенное событие scrollend браузера, если оно доступно. Если он недоступен, скрипт отслеживает события указателя и прокрутки, чтобы максимально точно оценить окончание события.
Примеры использования
Рекомендуется избегать ресурсоемких операций во время прокрутки. Это позволяет использовать для прокрутки столько памяти и вычислительных ресурсов, сколько необходимо для ее плавности. Событие scrollend – идеальный момент для вызова и выполнения тяжелой работы, поскольку прокрутка больше не происходит.
Событие scrollend может использоваться для запуска различных действий. Распространенный вариант использования – синхронизация связанных элементов пользовательского интерфейса с позицией, в которой прокрутка остановилась. Например:
- Синхронизация позиции прокрутки карусели с точечным индикатором.
- Синхронизация элемента галереи с его метаданными.
- Получение данных после того, как пользователь переходит на новую вкладку.
Представьте себе сценарий, в котором пользователь смахивает электронное письмо. После того, как они закончат пролистывание, вы можете выполнить действие в зависимости от того, куда они прокрутили.
Вы также можете использовать это событие для синхронизации после программной или пользовательской прокрутки или таких действий, как регистрация аналитики.
Вот хороший пример, когда несколько элементов, таких как стрелки, точки и фокус, необходимо обновить в зависимости от положения прокрутки. Посмотрите, как я создал эту карусель на YouTube. Вы также можете попробовать демоверсию.
Благодарим Мехди Каземи (Mehdi Kazemi) за работу над этой функцией и Роберта Флэка (Robert Flack) за помощь с API и реализацией.