È possibile animare scrollTop con jQuery?


226

Voglio scorrere senza intoppi verso il basso. Non voglio scrivere una funzione per questo, specialmente se jQuery ne ha già una.

Risposte:


463

Puoi semplicemente usare .animate()la scrollTopproprietà, in questo modo:

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

Molto bello .. non c'è bisogno di usare plugin per questo.
Amol M Kulkarni

15
Perché hai bisogno di entrambi htmle body? C'è qualche intuizione qui: stackoverflow.com/questions/2123690/… , ma non è una risposta completa.
Haralan Dobrev,

28
body è usato da webkit, html è usato da firefox.
Jory

2
FYI: Se <html>ha overflow-x:hidden;questo animato non funzionerà. (Potrebbe non funzionare per overflow-y:hidden, e overflow:hidden, ma non ho testato.
Collinhaines,

1
Penso che abbia bodyfunzionato in Chrome all'inizio di quest'anno, ma ora deve esserlo html.
Nick Davies l'

73

La risposta di Nick funziona benissimo. Fai attenzione quando specifichi una funzione complete () all'interno della chiamata animate () perché verrà eseguita due volte poiché hai dichiarato due selettori (html e body).

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

Ecco come evitare il doppio callback.

var completeCalled = false;
$("html, body").animate(
    { scrollTop: "300px" },
    {
        complete : function(){
            if(!completeCalled){
                completeCalled = true;
                alert('this alert will popup once');
            }
        }
    }
);

1
La domanda è: perché dovresti animare "html, body" e non solo "body"?
Lior,

21
Perché a seconda del browser che si è, è possibile animare body O html. Animando ENTRAMBE, copri più browser.
Bene

Ma in questo caso verrà pop-up solo una volta, anche se deve essere chiamato ripetutamente (fare clic sull'evento sul pulsante) o mi sono perso qualcosa?
HoGo

Sì, in questo caso verrà visualizzata una sola volta. Se è necessario animare ripetutamente, è necessario rendere locale la variabile completeCalled alla funzione di callback che esegue la funzione di animazione. In questo modo verrà comunque visualizzato solo una volta quando si fa clic, ma verrà nuovamente visualizzato (solo una volta) quando si fa di nuovo clic.
Kita,

Per evitare l'attivazione della doppia funzione di richiamata è possibile utilizzare la die()funzione prima della live()chiamata di funzione. Questo garantisce che il tuo live()gestore verrà chiamato una sola volta.
Lord Nighton,

27

La risposta di Nick funziona benissimo e le impostazioni predefinite sono buone, ma puoi controllare più completamente lo scorrimento completando tutte le impostazioni opzionali.

ecco come appare nell'API:

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

così potresti fare qualcosa del genere:

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

ecco la pagina API di jQuery .animate: http://api.jquery.com/animate/


15

Come accennato da Kita, c'è un problema con l'attivazione di più callback quando si animano sia "html" che "body". Invece di animare entrambi e bloccare i callback successivi, preferisco usare alcune funzionalità di rilevamento di base e animare solo la proprietà scrollTop di un singolo oggetto.

La risposta accettata su questo altro thread fornisce alcune informazioni su quale proprietà scrollTop dell'oggetto dovremmo provare ad animare: pageYOffset Scorrimento e animazione 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...
    })
});

AGGIORNARE - - -

Il precedente tentativo di rilevamento delle funzioni ha esito negativo. Sembra che non ci sia un modo su una riga per farlo come browser di tipo webkit La proprietà pageYOffset restituisce sempre zero quando c'è un tipo di documento. Invece, ho trovato il modo di usare una promessa per fare un singolo callback ogni volta che l'animazione viene eseguita.

$('html, body')
    .animate({ scrollTop: 100 })
    .promise()
    .then(function(){
        // callback code here
    })
});

1
L'uso di promise () qui è geniale.
Allan Bazinet,

Ciò richiede più voti. Non ho mai visto promesse usate prima per questo, e questo è qualcosa che finisco per cercare ogni pochi mesi. Come ha detto Allan, genio.
Tortilaman,

14

Ho quello che credo sia una soluzione migliore $('html, body')dell'hacking.

Non è un one-liner, ma il problema che ho avuto $('html, body')è che se accedi$(window).scrollTop() durante l'animazione, vedrai che il valore salta dappertutto, a volte di centinaia di pixel (anche se non vedo nulla del genere) accadendo visivamente). Avevo bisogno che il valore fosse prevedibile, in modo da poter annullare l'animazione se l'utente avesse afferrato la barra di scorrimento o ruotato la rotellina del mouse durante lo scorrimento automatico.

Ecco una funzione che animerà lo scorrimento senza intoppi:

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);
            }
        });
    }
}

Di seguito è una versione più complessa che annullerà l'animazione sull'interazione dell'utente, oltre a rifiutare fino al raggiungimento del valore target, utile quando si tenta di impostare istantaneamente ScrollTop (ad esempio semplicemente chiamando $(window).scrollTop(1000)- nella mia esperienza, questo non funziona su Il 50% delle volte.)

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);
                    }
                }
            }
        );
    }
}

7

Ho riscontrato problemi in cui l'animazione iniziava sempre dalla parte superiore della pagina dopo un aggiornamento della pagina negli altri esempi.

Ho risolto questo problema non animando direttamente il CSS ma piuttosto chiamando window.scrollTo();ogni passaggio:

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

Questo aggira anche il problema htmlvs bodyin quanto utilizza JavaScript cross-browser.

Dai un'occhiata a http://james.padolsey.com/javascript/fun-with-jquerys-animate/ per maggiori informazioni su cosa puoi fare con la funzione animata di jQuery.


5

È possibile utilizzare l'animazione jQuery per la pagina di scorrimento con una durata specifica:

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

dove 1024px è l'offset di scorrimento e 5000 è la durata delle animazioni in millisecondi.


Bella risposta! Sono contento di aver incluso l'opzione di durata. Volevo solo aggiungere che $("html, body").animate({scrollTop: 1024}, 5000);funziona anche.
Ryan Taylor,

4

Prova il plugin scrollTo .


Sembra che scrollTo non sia più un progetto in quel sito.
Jim,

Il codice per raggiungere questo obiettivo è così semplice. Perché dovresti aggiungere un plugin per fare qualcosa che puoi fare con una riga di codice?
Gavin,

4
Quattro anni fa non era così semplice .. :)
Tatu Ulmanen,

4
$(".scroll-top").on("click", function(e){
   e.preventDefault();
   $("html, body").animate({scrollTop:"0"},600);
});

1

Se vuoi spostarti verso il basso alla fine della pagina (quindi non è necessario scorrere verso il basso), puoi utilizzare:

$('body').animate({ scrollTop: $(document).height() });

0

Ma se vuoi davvero aggiungere qualche animazione mentre scorri, puoi provare il mio semplice plugin ( AnimateScroll ) che attualmente supporta più di 30 stili di


-3

il codice cross browser è:

$(window).scrollTop(300); 

è senza animazione ma funziona ovunque


6
Stavo cercando un modo "per animare scrollTop con jQuery?" Una risposta "senza animazione" non è una risposta.
Bryan Field,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.