Płynne przewijanie do określonego elementu DIV po kliknięciu

94

Próbuję zrobić to tak, aby po kliknięciu przycisku przewijał się (płynnie) w dół do określonego elementu div na stronie.

Potrzebuję tego, że jeśli klikniesz przycisk, płynnie przewinie się do „sekundy” div.

.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>

Erik Fischer
źródło
Możesz wypróbować tę wtyczkę, chociaż ta jest znacznie bardziej przyjazna dla użytkownika. Wystarczy, że połączysz plik JS w nagłówku i odpowiednio zmienisz znaczniki, aby działał.
joshrathke
1
to powinno ci pomóc :: stackoverflow.com/questions/3432656/ ...
Sudhir Bastakoti

Odpowiedzi:

178

zrobić:

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

Zaktualizowano Jsfiddle

Sudhir Bastakoti
źródło
Czy używasz tutaj javaScript czy jQuery?
1
@FahadUddin jego jQuery.
Sudhir Bastakoti,
@SudhirBastakoti: Dlaczego JsFiddle nie umieścił biblioteki jquery na tej stronie?
@Sudhir Bastakoti, ale wielu użytkowników skarży się, że nie jest to płynne przewijanie.
Maulik
40

Istnieje wiele przykładów płynnego przewijania przy użyciu bibliotek JS, takich jak jQuery, Mootools, Prototype itp.

Poniższy przykład dotyczy czystego JavaScript. Jeśli nie masz jQuery / Mootools / Prototype na stronie lub nie chcesz przeładowywać strony ciężkimi bibliotekami JS, przykład będzie pomocny.

http://jsfiddle.net/rjSfP/

Część HTML:

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

Część CSS:

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

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

Część 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);
}
nico
źródło
Używam tego i działa świetnie. Jak jednak spowolnić przewijanie?
jamescampbell
Masz jakiś pomysł, jak dodać przesunięcie dla stałego paska nawigacyjnego w tym kodzie? Oto przykład, który zrobiłem na skrzypcach
Plavookac
3
Nadal pomocny po 5 latach
Owaiz Yusufi
9

Bawiłem się trochę odpowiedzią nico i poczułem się nerwowo. Zrobiłem trochę badania i odkryłem, window.requestAnimationFramektóra jest funkcją, która jest wywoływana w każdym cyklu ponownego malowania. Pozwala to na bardziej przejrzystą animację. Nadal próbuję doskonalić dobre wartości domyślne dla rozmiaru kroku, ale dla mojego przykładu rzeczy wyglądają całkiem dobrze przy użyciu tej implementacji.

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);
}
Ned Rockson
źródło
1
@Alfonso Patrz wyżej. To jest po prostu zoptymalizowana wersja kodu nico w poprzedniej odpowiedzi.
Ned Rockson
@NedRockson Nie działa dla mnie wyświetla komunikat konsoli „Uncaught TypeError: Cannot read property 'parentNode' of null”, ale kod nico działa, co mam zrobić, aby zastosować czystą animację?
Kartik Watwani
@KartikWatwani Oznacza to, że w czytaniu wiersza scrollContainer = scrollContainer.parentNodescrollContainer ma wartość null. Prawdopodobnie oznacza to, że elementIdwywołując tę ​​funkcję, nie przekazujesz poprawnego wyniku. Możliwe jest również, że uruchamiasz ten skrypt na stronie, na której ten elementId nie istnieje.
Ned Rockson
@NedRockson Gdyby elementIdbyło źle, otrzymałbym ten sam błąd w przypadku przykładu @nico, ale w tym przypadku przewijanie działa, ale nie płynnie.
Kartik Watwani
Używanie requestAnimationFramezamiast setTimeoutto najlepszy sposób. setTimeoutnie powinny być używane do animacji.
tsnkff
2

Wziąłem wersję Neda Rocksona i dostosowałem ją tak, aby umożliwiała również przewijanie w górę.

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);
};
Marek Lisý
źródło
2

Możesz użyć podstawowego CSS, aby uzyskać płynne przewijanie

html {
  scroll-behavior: smooth;
}
Sardorbek Khalimov
źródło
0

Ned Rockson w zasadzie odpowiada na to pytanie. Jednak w jego rozwiązaniu jest fatalna wada. Gdy docelowy element znajduje się bliżej dołu strony niż viewport-height, funkcja nie osiąga instrukcji wyjścia i zatrzymuje użytkownika na dole strony. Można to po prostu rozwiązać, ograniczając liczbę iteracji.

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);
}
Programator pasywny
źródło