Ist es möglich, scrollTop mit jQuery zu animieren?

226

Ich möchte reibungslos nach unten scrollen. Ich möchte dafür keine Funktion schreiben müssen - besonders wenn jQuery bereits eine hat.

Bryan Field
quelle

Antworten:

463

Sie können .animate()die scrollTopEigenschaft einfach wie folgt verwenden:

$("html, body").animate({ scrollTop: "300px" });
Nick Craver
quelle
Sehr schön .. keine Notwendigkeit, Plugins dafür zu verwenden.
Amol M Kulkarni
15
Warum brauchst du beides htmlund body? Hier gibt es einige Einblicke: stackoverflow.com/questions/2123690/… , aber es ist keine vollständige Antwort.
Haralan Dobrev
28
body wird vom Webkit verwendet, HTML wird von Firefox verwendet.
Jory
2
Zur Info: Wenn <html>hat overflow-x:hidden;diese belebter wird nicht funktionieren. (Könnte nicht funktionieren für overflow-y:hidden, und overflow:hidden, aber ich habe nicht getestet.
Collinhaines
1
Ich denke, ich habe bodyAnfang dieses Jahres in Chrome gearbeitet, aber jetzt muss es so sein html.
Nick Davies
73

Nicks Antwort funktioniert großartig. Seien Sie vorsichtig, wenn Sie eine vollständige () Funktion im animate () -Aufruf angeben, da diese zweimal ausgeführt wird, da zwei Selektoren deklariert sind (HTML und Body).

$("html, body").animate(
    { scrollTop: "300px" },
    {
        complete : function(){
            alert('this alert will popup twice');
        }
    }
);

So können Sie den doppelten Rückruf vermeiden.

var completeCalled = false;
$("html, body").animate(
    { scrollTop: "300px" },
    {
        complete : function(){
            if(!completeCalled){
                completeCalled = true;
                alert('this alert will popup once');
            }
        }
    }
);
Kita
quelle
1
Die Frage ist, warum würden Sie "HTML, Körper" und nicht nur "Körper" animieren?
Lior
21
Denn je nachdem, welcher Browser Sie sind, können Sie entweder body oder html animieren. Indem Sie BEIDE animieren, decken Sie mehr Browser ab.
Bene
Aber in diesem Fall wird es wirklich nur einmal angezeigt, auch wenn es wiederholt aufgerufen werden muss (klicken Sie auf Ereignis auf Schaltfläche) oder habe ich etwas verpasst?
HoGo
Ja, in diesem Fall wird es nur einmal angezeigt. Wenn Sie wiederholt animieren müssen, würden Sie die Variable completeCalled lokal für die Rückruffunktion machen, die die Animationsfunktion ausführt. Auf diese Weise wird es beim Klicken immer noch nur einmal angezeigt, beim erneuten Klicken jedoch nur einmal (nur einmal).
Kita
Um zu verhindern, dass eine doppelte Rückruffunktion ausgelöst wird, können Sie die die()Funktion vor dem live()Funktionsaufruf verwenden. Dies garantiert, dass Ihr live()Handler nur einmal angerufen wird.
Lord Nighton
27

Nicks Antwort funktioniert hervorragend und die Standardeinstellungen sind nett, aber Sie können das Scrollen besser steuern, indem Sie alle optionalen Einstellungen vornehmen.

So sieht es in der API aus:

.animate( properties [, duration] [, easing] [, complete] )

Sie könnten also so etwas tun:

.animate( 
    {scrollTop:'300px'},
    300,
    swing,
    function(){ 
       alert(animation complete! - your custom code here!); 
       } 
    )

Hier ist die API-Seite der jQuery .animate-Funktion: http://api.jquery.com/animate/

Pfadfinder
quelle
15

Wie Kita bereits erwähnt hat, gibt es ein Problem mit mehreren Rückrufen, die ausgelöst werden, wenn Sie sowohl auf "HTML" als auch auf "Body" animieren. Anstatt beide zu animieren und nachfolgende Rückrufe zu blockieren, bevorzuge ich die Erkennung grundlegender Funktionen und animiere nur die scrollTop-Eigenschaft eines einzelnen Objekts.

Die akzeptierte Antwort in diesem anderen Thread gibt einen Einblick in die scrollTop-Eigenschaft des Objekts, die wir animieren sollten: pageYOffset Scrolling and Animation in IE8

// UPDATE: don't use this... see below
// only use 'body' for IE8 and below
var scrollTopElement = (window.pageYOffset != null) ? 'html' : 'body';

// only animate on one element so our callback only fires once!
$(scrollTopElement).animate({ 
        scrollTop: '400px' // vertical position on the page
    },
    500, // the duration of the animation 
    function() {       
        // callback goes here...
    })
});

UPDATE - - -

Der obige Versuch zur Feature-Erkennung schlägt fehl. Es scheint, als gäbe es keine einzeilige Möglichkeit, dies zu tun, da die pageYOffset-Eigenschaft eines Browsers vom Typ Webkit immer Null zurückgibt, wenn ein Doctype vorhanden ist. Stattdessen habe ich einen Weg gefunden, ein Versprechen zu verwenden, um bei jeder Ausführung der Animation einen einzelnen Rückruf durchzuführen.

$('html, body')
    .animate({ scrollTop: 100 })
    .promise()
    .then(function(){
        // callback code here
    })
});
Stephen
quelle
1
Versprechen () hier zu verwenden ist genial.
Allan Bazinet
Dies erfordert mehr Upvotes. Ich habe noch nie ein Versprechen dafür gesehen, und das ist etwas, wonach ich alle paar Monate suche. Wie Allan sagte, Genie.
Tortilaman
14

Ich habe das, was ich für eine bessere Lösung $('html, body')halte als den Hack.

Es ist kein Einzeiler, aber das Problem, das ich hatte, $('html, body')ist, dass wenn Sie sich $(window).scrollTop()während der Animation anmelden , Sie sehen, dass der Wert überall springt, manchmal um Hunderte von Pixeln (obwohl ich so etwas nicht sehe visuell geschehen). Der Wert musste vorhersehbar sein, damit ich die Animation abbrechen konnte, wenn der Benutzer während des automatischen Bildlaufs die Bildlaufleiste ergriff oder das Mausrad drehte.

Hier ist eine Funktion, die das reibungslose Scrollen animiert:

function animateScrollTop(target, duration) {
    duration = duration || 16;
    var scrollTopProxy = { value: $(window).scrollTop() };
    if (scrollTopProxy.value != target) {
        $(scrollTopProxy).animate(
            { value: target }, 
            { duration: duration, step: function (stepValue) {
                var rounded = Math.round(stepValue);
                $(window).scrollTop(rounded);
            }
        });
    }
}

Im Folgenden finden Sie eine komplexere Version, mit der die Animation bei Benutzerinteraktion abgebrochen und erneut ausgelöst wird, bis der Zielwert erreicht ist. Dies ist hilfreich, wenn Sie versuchen, das scrollTop sofort festzulegen (z. B. einfach aufrufen $(window).scrollTop(1000)- meiner Erfahrung nach funktioniert dies nicht 50% der Zeit.)

function animateScrollTop(target, duration) {
    duration = duration || 16;

    var $window = $(window);
    var scrollTopProxy = { value: $window.scrollTop() };
    var expectedScrollTop = scrollTopProxy.value;

    if (scrollTopProxy.value != target) {
        $(scrollTopProxy).animate(
            { value: target },
            {
                duration: duration,

                step: function (stepValue) {
                    var roundedValue = Math.round(stepValue);
                    if ($window.scrollTop() !== expectedScrollTop) {
                        // The user has tried to scroll the page
                        $(scrollTopProxy).stop();
                    }
                    $window.scrollTop(roundedValue);
                    expectedScrollTop = roundedValue;
                },

                complete: function () {
                    if ($window.scrollTop() != target) {
                        setTimeout(function () {
                            animateScrollTop(target);
                        }, 16);
                    }
                }
            }
        );
    }
}
John Starr Dewar
quelle
7

Ich hatte Probleme, bei denen die Animation nach einer Seitenaktualisierung in den anderen Beispielen immer oben auf der Seite begann.

Ich habe dies behoben, indem ich das CSS nicht direkt animiert habe, sondern window.scrollTo();jeden Schritt aufgerufen habe :

$({myScrollTop:window.pageYOffset}).animate({myScrollTop:300}, {
  duration: 600,
  easing: 'swing',
  step: function(val) {
    window.scrollTo(0, val);
  }
});

Dies umgeht auch das htmlvs- bodyProblem, da es browserübergreifendes JavaScript verwendet.

Werfen Sie einen Blick auf http://james.padolsey.com/javascript/fun-with-jquerys-animate/ für weitere Informationen darüber , was Sie mit jQuery animieren Funktion tun können.

komplistisch
quelle
5

Sie können die jQuery-Animation für Bildlaufseiten mit einer bestimmten Dauer verwenden:

$("html, body").animate({scrollTop: "1024px"}, 5000);

Dabei ist 1024px der Bildlaufversatz und 5000 die Dauer der Animationen in Millisekunden.

Alessandro Pirovano
quelle
Gute Antwort! Ich bin froh, dass Sie die Daueroption aufgenommen haben. Ich wollte nur hinzufügen, dass das $("html, body").animate({scrollTop: 1024}, 5000);auch funktioniert.
Ryan Taylor
4

Probieren Sie das scrollTo- Plugin aus.

Tatu Ulmanen
quelle
Es scheint, dass scrollTo an dieser Site kein Projekt mehr ist.
Jim
Der Code, um dies zu erreichen, ist so einfach. Warum sollten Sie ein Plugin hinzufügen, um etwas zu tun, das Sie mit einer Codezeile tun können?
Gavin
4
Vor vier Jahren war es nicht so einfach .. :)
Tatu Ulmanen
4
$(".scroll-top").on("click", function(e){
   e.preventDefault();
   $("html, body").animate({scrollTop:"0"},600);
});
Rubel Hossain
quelle
1

Wenn Sie am Ende der Seite nach unten gehen möchten (damit Sie nicht nach unten scrollen müssen), können Sie Folgendes verwenden:

$('body').animate({ scrollTop: $(document).height() });
Kleine Ameise
quelle
-3

Der browserübergreifende Code lautet:

$(window).scrollTop(300); 

Es ist ohne Animation, funktioniert aber überall

user2760861
quelle
6
Ich suchte nach einer Möglichkeit, "scrollTop mit jQuery zu animieren?" Eine Antwort "ohne Animation" ist keine Antwort.
Bryan Field