Страницы

Поиск по вопросам

суббота, 30 ноября 2019 г.

Плавная прокрутка к якорю без jQuery

#javascript #jquery


Есть отличный скрипт плавной прокрутки на jQuery.

var $page = $('html, body');
$('a[href*="#"]').click(function() {
    $page.animate({
        scrollTop: $($.attr(this, 'href')).offset().top
    }, 400);
    return false;
});


Как можно отобразить на чистом JS?
    


Ответы

Ответ 1



// собираем все якоря; устанавливаем время анимации и количество кадров const anchors = [].slice.call(document.querySelectorAll('a[href*="#"]')), animationTime = 300, framesCount = 20; anchors.forEach(function(item) { // каждому якорю присваиваем обработчик события item.addEventListener('click', function(e) { // убираем стандартное поведение e.preventDefault(); // для каждого якоря берем соответствующий ему элемент и определяем его координату Y let coordY = document.querySelector(item.getAttribute('href')).getBoundingClientRect().top + window.pageYOffset; // запускаем интервал, в котором let scroller = setInterval(function() { // считаем на сколько скроллить за 1 такт let scrollBy = coordY / framesCount; // если к-во пикселей для скролла за 1 такт больше расстояния до элемента // и дно страницы не достигнуто if(scrollBy > window.pageYOffset - coordY && window.innerHeight + window.pageYOffset < document.body.offsetHeight) { // то скроллим на к-во пикселей, которое соответствует одному такту window.scrollBy(0, scrollBy); } else { // иначе добираемся до элемента и выходим из интервала window.scrollTo(0, coordY); clearInterval(scroller); } // время интервала равняется частному от времени анимации и к-ва кадров }, animationTime / framesCount); }); }); h2 { margin-bottom: 100vh; }

heading 1

heading 2

heading 3

heading 4



Ответ 2



Кросплатформенный вариант: currentYPosition - определяет текущее положение скрола elmYPosition - определяет положение элемента smoothScroll - собственно сама функция. function currentYPosition() { // Firefox, Chrome, Opera, Safari if (self.pageYOffset) return self.pageYOffset; // Internet Explorer 6 - standards mode if (document.documentElement && document.documentElement.scrollTop) return document.documentElement.scrollTop; // Internet Explorer 6, 7 and 8 if (document.body.scrollTop) return document.body.scrollTop; return 0; } function elmYPosition(eID) { var elm = document.getElementById(eID); var y = elm.offsetTop; var node = elm; while (node.offsetParent && node.offsetParent != document.body) { node = node.offsetParent; y += node.offsetTop; } return y; } function smoothScroll(eID) { var startY = currentYPosition(); var stopY = elmYPosition(eID); var distance = stopY > startY ? stopY - startY : startY - stopY; if (distance < 100) { scrollTo(0, stopY); return; } var speed = Math.round(distance / 100); if (speed >= 20) speed = 20; var step = Math.round(distance / 25); var leapY = stopY > startY ? startY + step : startY - step; var timer = 0; if (stopY > startY) { for ( var i=startY; i stopY) leapY = stopY; timer++; } return; } for ( var i=startY; i>stopY; i-=step ) { setTimeout("window.scrollTo(0, "+leapY+")", timer * speed); leapY -= step; if (leapY < stopY) leapY = stopY; timer++; } } Ответ взят отсюда Упрощенная версия, когда надо просто проскролить к определенной позиции function scrollTo(element, to, duration) { if (duration <= 0) return; var difference = to - element.scrollTop; var perTick = difference / duration * 10; setTimeout(function() { element.scrollTop = element.scrollTop + perTick; if (element.scrollTop === to) return; scrollTo(element, to, duration - 10); }, 10); } Ответ взят отсюда

Ответ 3



Есть еще стандартный способ плавной прокрутки Element.scrollIntoView(). const anchors = document.querySelectorAll('a[href*="#"]') for (let anchor of anchors) { anchor.addEventListener('click', function (e) { e.preventDefault() const blockID = anchor.getAttribute('href').substr(1) document.getElementById(blockID).scrollIntoView({ behavior: 'smooth', block: 'start' }) }) } h2 { margin-bottom: 100vh; }

heading 1

heading 2

heading 3

heading 4



Ответ 4



var nodeObj = document.querySelector('.button-node'); nodeObj.scrollIntoView({ behavior: "smooth", block: "start" });

Ответ 5



const anim = (sel, duration) => { let to = document.querySelector(sel).getBoundingClientRect().top, temp; return (sel) => { cancelAnimationFrame(temp); var start = performance.now(); var from = window.pageYOffset || document.documentElement.scrollTop; requestAnimationFrame(function step(timestamp) { var progress = (timestamp - start) / duration; 1 <= progress && (progress = 1); window.scrollTo(0, from + to * progress | 0); 1 > progress && (temp = requestAnimationFrame(step)) }); } }

Комментариев нет:

Отправить комментарий