Плавне прокручування до певного 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 / ...
Судхиром Bastakoti

Відповіді:


178

робити:

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

Оновлено Jsfiddle


Ви використовуєте тут javaScript або jQuery?

1
@FahadUddin його jQuery.
Судхір Бастакоті

@SudhirBastakoti: Чому JsFiddle не включив для неї бібліотеку jquery на цю сторінку?

@Sudhir Bastakoti, але багато користувачів скаржаться, що це не плавне прокручування.
Маулік

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 Див. Вище. Це просто оптимізована версія коду nico у попередній відповіді.
Нед Роксон,

@NedRockson Не працює для мене, видає консольне повідомлення "Uncaught TypeError: Не вдається прочитати властивість 'parentNode' з нулем", але код nico працює, Що мені робити, щоб застосувати чисту анімацію?
Kartik Watwani

@KartikWatwani Це означає, що при зчитуванні рядка scrollContainer = scrollContainer.parentNodescrollContainer має значення null. Це, ймовірно, означає, що ви не передаєте правильну інформацію elementIdпід час виклику цієї функції. Також можливо, що ви запускаєте цей сценарій на сторінці, де цей елемент-ідентифікатор не існує.
Нед Роксон,

@NedRockson Якщо elementIdб це було неправильно, я отримав би таку ж помилку у випадку прикладу @nico, але в цьому випадку прокрутка працює, але не плавно.
Kartik Watwani

Використання 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);
};


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);
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.