Задача на сегодня - плавная прокрутка страницы (или любого компонента с полосой прокрутки) на чистом Javascript без использования дополнительных библиотек.
Разберем несколько вариантов реализации поставленной задачи.
Вариант №0 - моментальная прокрутка
По-умолчанию программная прокрутка выполняется мгновенно, и для того, чтобы было от чего отталкиваться, напишем стандартную функцию прокрутки:
function gotop() {
document.scrollingElement.scrollTop = 0;
// эквивалент: document.scrollingElement.scrollTo(0, 0);
}
Более детально: scrollTo(x, y), и scrollTop.
Браузер при этом просто переносит положение скроллера на указанную позицию, без использования какой-либо анимации.
Вариант №1 - наверх за 500мс
Реализуем вариант, когда необходимо прокрутить элемент с любой позиции за 500мс. То есть, не важно на какой позиции находится скроллер, прокрутка всегда будет выполняться за 500мс. Таким образом, чем меньше расстояние от текущей позиции до цели - тем медленнее будет выглядеть анимация прокрутки.
Для реализации данного варианта нам потребется стандартная javascript функция setInterval.
Алгоритм заключается в следующем:
- задаём время, за которое необходимо выполнить прокрутку - 500мс
- задаём необходимую плавность, т.е. интервал времени между сдвигами, например, 20мс
- вычисляем сколько понадобится сдвигов: 500 мс / 20 мс = 25 сдвигов
- вычисляем размер одного сдвига в пикселях, разделив расстояние прокрутки на количество сдвигов: (позиция - цель) / 25 сдвигов
function gotopPer500ms() {
const target = 0;
const smoothless = 20;
const time = 500;
const shift = (el.scrollTop - target) / (time / smoothless);
const timer = setInterval(() => {
el.scrollTop = Math.max(target, el.scrollTop - shift);
if (target === el.scrollTop) clearInterval(timer);
}, smoothless);
}
Вариант №2 - наверх с анимацией
Этот вариант предполагает использование функции requestAnimationFrame. Реализация аналогична предыдущему варианту, за исключением того, что за плавность прокрутки будет отвечать частота перерисовки страницы браузером.
function gotopAnimate() {
const target = 0;
const speed = 0.5;
const shift = el.offsetHeight * speed / 100;
function _step(timestamp) {
el.scrollTop = Math.max(target, el.scrollTop - shift);
if (target !== el.scrollTop) window.requestAnimationFrame(_step);
}
window.requestAnimationFrame(_step);
}
Поддерживаемость данной функции браузерами весьма высока - 96.43% (источник)
То же самое, но через setInterval:
function gotopConstSpeed() {
const target = 0;
const speed = 0.5;
const smoothless = 20;
const shift = el.offsetHeight * speed / 100;
const timer = setInterval(() => {
el.scrollTop = Math.max(target, el.scrollTop - shift);
if (target === el.scrollTop) clearInterval(timer);
}, smoothless);
}
Если сравнить реализации на requestAnimationFrame и setInterval, то в случае setInterval на низких скоростях прокрутка выглядит слегка рваной, в то время как реализация на requestAnimationFrame сохраняет плавность хода.
Вариант №3 - наверх в одну строку
Предыдущие варианты предполагают вашу собственную реализацию способа прокрутки, но если не так важна реализация, сколько сам факт плавности, то есть решение в одну строку. Этот вариант использует стандартный способ плавной прокрутки, реализованный в каждом браузере по-своему.
Вызываем функцию scrollTo и передаем объект в качестве параметра:
function gotopSmooth() {
el.scrollTo({top: 0, behavior: 'smooth'}); // поддерживаемость браузерами 86.67%
}
Стоит учитывать, что поддержка различными браузерами scrollTop - 95.12%, а scrollTo({behavior}) - 86.67% (источник)
Сравнение вариантов на живом примере
Посмотреть на работу каждого из методов и сравнить реализации можно на отдельной странице: https://asilichenko.blogspot.com/p/blog-page.html
No comments:
Post a Comment