É possível animar o scrollTop com jQuery?

Quero descer suavemente. Eu não quero ter que escrever uma função para isso - especialmente se jQuery já tem um.

Author: George Bailey, 2010-10-27

12 answers

Podes usar .animate() a propriedade scrollTop, assim:

$("html, body").animate({ scrollTop: "300px" });
 444
Author: Nick Craver, 2010-10-27 18:27:44
A resposta do Nick funciona muito bem. Tenha cuidado ao especificar uma função completa() dentro da chamada animate () porque ela será executada duas vezes, uma vez que você tem dois seletores declarados (html e corpo).
$("html, body").animate(
    { scrollTop: "300px" },
    {
        complete : function(){
            alert('this alert will popup twice');
        }
    }
);
Eis como podes evitar o duplo callback.
var completeCalled = false;
$("html, body").animate(
    { scrollTop: "300px" },
    {
        complete : function(){
            if(!completeCalled){
                completeCalled = true;
                alert('this alert will popup once');
            }
        }
    }
);
 70
Author: Kita, 2012-02-20 10:28:56

A resposta do Nick funciona muito bem e as configurações por omissão são boas, mas você pode controlar mais completamente a rolagem, completando todas as configurações opcionais.

Aqui está o que parece na API:
.animate( properties [, duration] [, easing] [, complete] )
Para que pudesses fazer algo assim.
.animate( 
    {scrollTop:'300px'},
    300,
    swing,
    function(){ 
       alert(animation complete! - your custom code here!); 
       } 
    )
Aqui está o jQuery .animar a página da api da função: http://api.jquery.com/animate/
 25
Author: pathfinder, 2011-10-15 17:37:24
Tenho o que acredito ser uma solução melhor do que a invasão.

Não É um one-liner, mas o problema que eu tinha com $('html, body') é que se você log $(window).scrollTop() durante a animação, você verá que o valor de saltos em todo o lugar, às vezes por centenas de pixels (apesar de eu não ver nada acontecer visualmente). Eu precisava do valor para ser previsível, para que eu pudesse cancelar a animação se o usuário pegasse a barra de pergaminho ou girasse a roda do mousewheel durante o auto-rolar.

Aqui está uma função que irá animar a rolagem suavemente:

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

Abaixo é mais complexo, versão que irá cancelar a animação de interação com o usuário, bem como refiring até que o valor alvo é atingido, o que é útil quando se tenta definir o scrollTop instantaneamente (e.g. simplesmente chamando $(window).scrollTop(1000) - na minha experiência, esta não funcionar cerca de 50% do tempo.)

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);
                    }
                }
            }
        );
    }
}
 14
Author: John Starr Dewar, 2013-12-20 08:20:47

Tal como o Kita mencionou, há um problema com vários callbacks a disparar quando se anima tanto em 'html' como em 'body'. Em vez de animar ambos e bloquear posteriores callbacks eu prefiro usar alguma detecção de recursos básicos e apenas animar a propriedade de scrollTop de um único objeto.

A resposta aceite neste outro tópico dá alguma ideia sobre qual a propriedade de posicionamento do objecto que devemos tentar animar: 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...
    })
});

Actualização - - -

A tentativa de detecção de características acima falha. Parece que não há uma forma única de fazê-lo como WebKit browsers pageyoffset property sempre retorna zero quando há um doctype. Em vez disso, eu encontrei uma maneira de usar uma promessa de fazer uma única chamada de volta para cada vez que a animação executa.

$('html, body')
    .animate({ scrollTop: 100 })
    .promise()
    .then(function(){
        // callback code here
    })
});
 11
Author: Stephen, 2017-05-23 11:47:20

Eu estava tendo problemas onde a animação estava sempre começando a partir do topo da página depois de uma atualização de página nos outros exemplos.

Corrigi isto não animando o css directamente, mas sim chamando window.scrollTo(); em cada passo:

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

Isto também contorna a questão html vs body porque está a usar o JavaScript do navegador cruzado.

Olha para http://james.padolsey.com/javascript/fun-with-jquerys-animate para mais informações sobre o que pode fazer com o jQuery animar a função.

 7
Author: complistic, 2014-05-27 01:44:52

Pode usar a animação jQuery para a página de posicionamento com uma duração específica:

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

Em que 1024px é o deslocamento do pergaminho e 5000 é a duração das animações em milissegundo.

 4
Author: Alessandro Pirovano, 2013-12-11 10:26:01

Tente oscrollTo plugin.

 4
Author: Tatu Ulmanen, 2014-09-24 08:02:56
$(".scroll-top").on("click", function(e){
   e.preventDefault();
   $("html, body").animate({scrollTop:"0"},600);
});
 2
Author: Rubel Hossain, 2017-03-08 13:06:59

Se quiser descer no fim da página ( por isso não precisa de descer para baixo), pode usar:

$('body').animate({ scrollTop: $(document).height() });
 1
Author: Small Ant, 2016-07-15 14:45:11

Mas se quiser mesmo adicionar alguma animação ao deslocar-se, poderá tentar o meu 'plugin' simples (AnimateScroll ) que suporta actualmente mais de 30 estilos de suavização

 0
Author: Ram Patra, 2013-09-12 09:24:28

O código do navegador cruzado é:

$(window).scrollTop(300); 

É sem animação mas funciona em todo o lado

 -3
Author: user2760861, 2013-09-09 09:26:23