Reibungsloser Bildlauf zu einem bestimmten Div beim Klicken

91

Ich versuche es so zu gestalten, dass beim Klicken auf eine Schaltfläche (reibungslos) zu einem bestimmten Div auf der Seite gescrollt wird.

Was ich brauche ist, wenn Sie auf die Schaltfläche klicken, wird sanft zur div 'Sekunde' gescrollt.

.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
quelle
Sie könnten dieses Plugin ausprobieren, obwohl dieses weitaus benutzerfreundlicher ist. Sie müssen so ziemlich nur die JS-Datei im Header verknüpfen und Ihr Markup entsprechend ändern, damit es funktioniert.
Joshrathke
1
Dies sollte Ihnen helfen :: stackoverflow.com/questions/3432656/…
Sudhir Bastakoti

Antworten:

177

machen:

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

Jsfiddle aktualisiert

Sudhir Bastakoti
quelle
Verwenden Sie hier JavaScript oder jQuery?
Fuddin
1
@FahadUddin seine jQuery.
Sudhir Bastakoti
@SudhirBastakoti: Warum hat die JsFiddle die jquery-Bibliothek dafür nicht auf dieser Seite aufgenommen?
Fuddin
@ Sudhir Bastakoti, aber viele Benutzer beschweren sich, dass es nicht reibungsloses Scrollen ist.
Maulik
39

Es gibt viele Beispiele für reibungsloses Scrollen mit JS-Bibliotheken wie jQuery, Mootools, Prototype usw.

Das folgende Beispiel bezieht sich auf reines JavaScript. Wenn Sie kein jQuery / Mootools / Prototype auf der Seite haben oder die Seite nicht mit umfangreichen JS-Bibliotheken überladen möchten, ist das Beispiel hilfreich.

http://jsfiddle.net/rjSfP/

HTML-Teil:

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

CSS-Teil:

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

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

JS Teil:

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
quelle
Ich benutze dies und es funktioniert großartig. Wie mache ich die Schriftrolle langsamer?
Jamescampbell
Haben Sie eine Idee, wie Sie in diesem Code einen Versatz für eine feste Navigationsleiste hinzufügen können? Hier ist ein Beispiel, das ich Geige gemacht habe
Plavookac
3
Nach 5 Jahren immer noch hilfreich
Owaiz Yusufi
9

Ich spielte ein wenig mit Nicos Antwort herum und es fühlte sich nervös an. Habe ein bisschen nachgeforscht und herausgefunden, window.requestAnimationFramewelche Funktion bei jedem Repaint-Zyklus aufgerufen wird. Dies ermöglicht eine sauberere Animation. Ich versuche immer noch, gute Standardwerte für die Schrittgröße zu verbessern, aber in meinem Beispiel sieht es mit dieser Implementierung ziemlich gut aus.

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
quelle
1
@ Alfonso Siehe oben. Dies ist einfach eine optimierte Version von Nicos Code in einer früheren Antwort.
Ned Rockson
@NedRockson Funktioniert nicht bei mir gibt die Konsolenmeldung "Uncaught TypeError: Eigenschaft 'parentNode' von null kann nicht gelesen werden", aber der Code von nico funktioniert. Was soll ich tun, um eine saubere Animation anzuwenden?
Kartik Watwani
@KartikWatwani Das bedeutet, dass scrollContainer beim Lesen der Zeile scrollContainer = scrollContainer.parentNodenull ist. Dies bedeutet wahrscheinlich, dass Sie elementIdbeim Aufrufen dieser Funktion nicht das Richtige übergeben . Es ist auch möglich, dass Sie dieses Skript auf einer Seite ausführen, auf der diese elementId nicht vorhanden ist.
Ned Rockson
@NedRockson Wenn elementIdes falsch gewesen wäre, hätte ich im Fall von @nicos Beispiel den gleichen Fehler erhalten, aber in diesem Fall funktioniert das Scrollen, aber nicht reibungslos.
Kartik Watwani
Verwenden requestAnimationFramestatt setTimeoutist der richtige Weg. setTimeoutsollte nicht für Animationen verwendet werden.
Tsnkff
2

Ich nahm die Version von Ned Rockson und passte sie an, um auch Schriftrollen nach oben zu ermöglichen.

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ý
quelle
0

Sie können einfaches CSS verwenden, um einen reibungslosen Bildlauf zu erzielen

html {
  scroll-behavior: smooth;
}
Sardorbek Khalimov
quelle