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

506
08 июня 2017, 08:55

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

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

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

Answer 1

Кросплатформенный вариант:

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; i+=step ) {
            setTimeout("window.scrollTo(0, "+leapY+")", timer * speed);
            leapY += step; if (leapY > 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);
}

Ответ взят отсюда

Answer 2

// собираем все якоря; устанавливаем время анимации и количество кадров 
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; 
     
    // запускаем интервал, в котором 
    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; 
}
<ul> 
  <li><a href="#head1">head 1</a> 
  <li><a href="#head2">head 2</a> 
  <li><a href="#head3">head 3</a> 
  <li><a href="#head4">head 4</a> 
</ul> 
 
<h2 id="head1">heading 1</h2> 
<h2 id="head2">heading 2</h2> 
<h2 id="head3">heading 3</h2> 
<h2 id="head4">heading 4</h2>

READ ALSO
Меню не исчезает при скролле

Меню не исчезает при скролле

У меня проблема, когда я скроллю страницу меню не исчезает/появляется вот код

256
Js regexp замена тегов

Js regexp замена тегов

Вопрос такой, как можно с помощью js regexp заменить 2 тега br на div

262
Как связать react и nw.js?

Как связать react и nw.js?

Вопрос в этом - что куда записать, чтобы при запуске nwjs запускалось приложение, написанное на react?

235
PHP Как убрать вывод значений на страницу

PHP Как убрать вывод значений на страницу

У меня при выборе даты заполняется выпадающий списокПосле нажатия на кнопку submit, значения, которыми заполняется выпадающий список, выводятся...

309