Плавная прокрутка к конкретному div при нажатии

94

Я пытаюсь сделать так, чтобы при нажатии на кнопку она плавно прокручивалась вниз до определенного блока div на странице.

Что мне нужно, так это то, что если вы нажмете на кнопку, она плавно прокрутится до div 'second'.

.first {
    width: 100%;
    height: 1000px;
    background: #ccc;
}

.second {
    width: 100%;
    height: 1000px;
    background: #999;
}
<div class="first"><button type="button">Click Me!</button></div>
<div class="second">Hi</div>

Эрик Фишер
источник
Вы можете попробовать этот плагин, хотя он гораздо удобнее для пользователя. Вам просто нужно связать JS-файл в заголовке и соответствующим образом изменить разметку, чтобы он работал.
joshrathke
1
это должно вам помочь :: stackoverflow.com/questions/3432656/…
Судхир Бастакоти 06

Ответы:

178

делать:

$("button").click(function() {
    $('html,body').animate({
        scrollTop: $(".second").offset().top},
        'slow');
});

Обновлен Jsfiddle

Судхир Бастакоти
источник
Вы здесь используете javaScript или jQuery?
1
@FahadUddin свой jQuery.
Судхир Бастакоти
@SudhirBastakoti: Почему JsFiddle не включил библиотеку jquery для него на этой странице?
@Sudhir Bastakoti, но многие пользователи жалуются, что это не плавная прокрутка.
Maulik
40

Существует множество примеров плавной прокрутки с использованием JS-библиотек, таких как jQuery, Mootools, Prototype и т. Д.

Следующий пример основан на чистом JavaScript. Если у вас нет jQuery / Mootools / Prototype на странице или вы не хотите перегружать страницу тяжелыми библиотеками JS, пример будет вам полезен.

http://jsfiddle.net/rjSfP/

HTML-часть:

<div class="first"><button type="button" onclick="smoothScroll(document.getElementById('second'))">Click Me!</button></div>
<div class="second" id="second">Hi</div>

Часть CSS:

.first {
    width: 100%;
    height: 1000px;
    background: #ccc;
}

.second {
    width: 100%;
    height: 1000px;
    background: #999;
}

Часть JS:

window.smoothScroll = function(target) {
    var scrollContainer = target;
    do { //find scroll container
        scrollContainer = scrollContainer.parentNode;
        if (!scrollContainer) return;
        scrollContainer.scrollTop += 1;
    } while (scrollContainer.scrollTop == 0);

    var targetY = 0;
    do { //find the top of target relatively to the container
        if (target == scrollContainer) break;
        targetY += target.offsetTop;
    } while (target = target.offsetParent);

    scroll = function(c, a, b, i) {
        i++; if (i > 30) return;
        c.scrollTop = a + (b - a) / 30 * i;
        setTimeout(function(){ scroll(c, a, b, i); }, 20);
    }
    // start scrolling
    scroll(scrollContainer, scrollContainer.scrollTop, targetY, 0);
}
Нико
источник
Я использую это, и он отлично работает. Как мне сделать прокрутку медленнее?
jamescampbell
Есть идеи, как добавить смещение для фиксированной панели навигации в этот код? Вот пример, который я сделал на скрипке
Plavookac
3
Все еще полезен после 5 лет
Овайз Юсуфи
9

Я немного поигрался с ответом Нико, и это показалось мне нервным. Провел небольшое исследование и обнаружил, window.requestAnimationFrameкакая функция вызывается в каждом цикле перерисовки. Это позволяет сделать анимацию более четкой. Все еще пытаюсь отточить хорошие значения по умолчанию для размера шага, но для моего примера с этой реализацией все выглядит довольно хорошо.

var smoothScroll = function(elementId) {
    var MIN_PIXELS_PER_STEP = 16;
    var MAX_SCROLL_STEPS = 30;
    var target = document.getElementById(elementId);
    var scrollContainer = target;
    do {
        scrollContainer = scrollContainer.parentNode;
        if (!scrollContainer) return;
        scrollContainer.scrollTop += 1;
    } while (scrollContainer.scrollTop == 0);

    var targetY = 0;
    do {
        if (target == scrollContainer) break;
        targetY += target.offsetTop;
    } while (target = target.offsetParent);

    var pixelsPerStep = Math.max(MIN_PIXELS_PER_STEP,
                                 (targetY - scrollContainer.scrollTop) / MAX_SCROLL_STEPS);

    var stepFunc = function() {
        scrollContainer.scrollTop =
            Math.min(targetY, pixelsPerStep + scrollContainer.scrollTop);

        if (scrollContainer.scrollTop >= targetY) {
            return;
        }

        window.requestAnimationFrame(stepFunc);
    };

    window.requestAnimationFrame(stepFunc);
}
Нед Роксон
источник
1
@Alfonso См. Выше. Это просто оптимизированная версия кода Нико из предыдущего ответа.
Нед Роксон 07
@NedRockson Не работает для меня, выдает консольное сообщение "Uncaught TypeError: Cannot read property 'parentNode' of null", но код Нико работает. Что мне делать, чтобы можно было применить чистую анимацию?
Kartik Watwani
@KartikWatwani Это означает, что в строке чтения scrollContainer = scrollContainer.parentNodescrollContainer имеет значение null. Это, вероятно, означает, что вы не передаете правильный код elementIdпри вызове этой функции. Также возможно, что вы запускаете этот скрипт на странице, где этот elementId не существует.
Нед Роксон
@NedRockson Если elementIdбы я ошибался, я бы получил ту же ошибку в случае с примером @nico, но в этом случае прокрутка работает, но не плавно.
Картик Ватвани
Использование requestAnimationFrameвместо setTimeout- лучший способ. setTimeoutне следует использовать для анимации.
tsnkff
2

Я взял версию Неда Роксона и отрегулировал ее, чтобы можно было прокручивать вверх.

var smoothScroll = function(elementId) {
  var MIN_PIXELS_PER_STEP = 16;
  var MAX_SCROLL_STEPS = 30;
  var target = document.getElementById(elementId);
  var scrollContainer = target;
  do {
    scrollContainer = scrollContainer.parentNode;
    if (!scrollContainer) return;
    scrollContainer.scrollTop += 1;
  } while (scrollContainer.scrollTop === 0);

  var targetY = 0;
  do {
    if (target === scrollContainer) break;
    targetY += target.offsetTop;
  } while (target = target.offsetParent);

  var pixelsPerStep = Math.max(MIN_PIXELS_PER_STEP,
    Math.abs(targetY - scrollContainer.scrollTop) / MAX_SCROLL_STEPS);

  var isUp = targetY < scrollContainer.scrollTop;

  var stepFunc = function() {
    if (isUp) {
      scrollContainer.scrollTop = Math.max(targetY, scrollContainer.scrollTop - pixelsPerStep);
      if (scrollContainer.scrollTop <= targetY) {
        return;
      }
    } else {
        scrollContainer.scrollTop = Math.min(targetY, scrollContainer.scrollTop + pixelsPerStep);

      if (scrollContainer.scrollTop >= targetY) {
        return;
      }
    }

    window.requestAnimationFrame(stepFunc);
  };

  window.requestAnimationFrame(stepFunc);
};
Марек Лисы
источник
2

Вы можете использовать базовый CSS для достижения плавной прокрутки

html {
  scroll-behavior: smooth;
}
Сардорбек Халимов
источник
0

Нед Роксон в основном отвечает на этот вопрос. Однако в его решении есть фатальный изъян. Когда целевой элемент находится ближе к низу страницы, чем высота области просмотра, функция не достигает своего оператора выхода и захватывает пользователя в нижней части страницы. Это просто решается ограничением количества итераций.

var smoothScroll = function(elementId) {
    var MIN_PIXELS_PER_STEP = 16;
    var MAX_SCROLL_STEPS = 30;
    var target = document.getElementById(elementId);
    var scrollContainer = target;
    do {
        scrollContainer = scrollContainer.parentNode;
        if (!scrollContainer) return;
        scrollContainer.scrollTop += 1;
    } while (scrollContainer.scrollTop == 0);

    var targetY = 0;
    do {
        if (target == scrollContainer) break;
        targetY += target.offsetTop;
    } while (target = target.offsetParent);

    var pixelsPerStep = Math.max(MIN_PIXELS_PER_STEP,
                                 (targetY - scrollContainer.scrollTop) / MAX_SCROLL_STEPS);

    var iterations = 0;
    var stepFunc = function() {
        if(iterations > MAX_SCROLL_STEPS){
            return;
        }
        scrollContainer.scrollTop =
            Math.min(targetY, pixelsPerStep + scrollContainer.scrollTop);

        if (scrollContainer.scrollTop >= targetY) {
            return;
        }

        window.requestAnimationFrame(stepFunc);
    };

    window.requestAnimationFrame(stepFunc);
}
Пассивный программист
источник