是否可以使用jQuery来使scrollTop动画化?


Answers:


463

您可以只使用.animate()scrollTop属性,如下所示:

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

非常好..无需为此使用插件。
Amol M Kulkarni

15
为什么同时需要htmlbody?这里有一些见解:stackoverflow.com/questions/2123690/…,但这不是一个完整的答案。
Haralan Dobrev 2013年

28
webkit使用body,firefox使用html。
2014年

2
仅供参考:如果<html>overflow-x:hidden;此动画,将不起作用。(可能不适合工作overflow-y:hidden,和overflow:hidden,但我没有测试。
collinhaines

1
我认为body从今年年初开始在Chrome中工作,但现在必须如此html
尼克·戴维斯

73

尼克的答案很好。在animate()调用中指定complete()函数时要小心,因为您有两个声明的选择器(html和body),它将被执行两次。

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

这是避免双重回调的方法。

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

1
问题是,为什么要设置“ html,body”而不是“ body”的动画?
Lior

21
因为取决于您使用的是哪种浏览器,所以可以为正文或html设置动画。通过同时设置动画,可以覆盖更多浏览器。
Bene

但是在这种情况下,它实际上只会弹出一次,如果必须反复调用(单击按钮上的单击事件),或者我错过了什么,还会弹出一次吗?
HoGo 2013年

是的,在这种情况下,它将仅弹出一次。如果需要重复设置动画,则可以将completeCalled变量设置为执行动画功能的回调函数的局部变量。这样,当您单击时,它仍将仅弹出一次,但是当您再次单击时,它将再次弹出(仅一次)。
Kita 2014年

为了防止触发双重回调函数,可以die()live()函数调用之前使用function 。这样可以保证您的live()处理程序仅被调用一次。
诺顿勋爵,2015年

27

Nick的答案效果很好,默认设置也不错,但是您可以通过完成所有可选设置来更全面地控制滚动。

这是API中的样子:

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

因此您可以执行以下操作:

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

这是jQuery .animate函数api页面:http ://api.jquery.com/animate/


15

就像Kita提到的那样,在“ html”和“ body”上设置动画时,会触发多个回调。我宁愿使用一些基本的功能检测,而仅对单个对象的scrollTop属性设置动画,而不是同时设置动画和阻止后续的回调。

另一个线程上的已接受答案给出了有关我们应尝试对其进行动画处理的对象的scrollTop属性的一些见解:pageYOffset 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...
    })
});

更新---

上面的特征检测尝试失败。似乎没有一种单行方法,因为webkit类型的浏览器的pageYOffset属性在存在doctype时总是返回零。相反,我找到了一种方法,可以在每次动画执行时使用promise进行单个回调。

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

1
在这里使用promise()是个天才。
艾伦·巴赞特

这需要更多的支持。我以前从未见过为此使用诺言,而这是我每隔几个月要寻找的东西。正如艾伦所说的,天才。
Tortilaman

14

我有比$('html, body')骇客更好的解决方案。

它不是单线的,但是我遇到的问题$('html, body')是,如果您$(window).scrollTop()在动画过程中记录日志,您会看到该值在整个地方跳跃,有时会跳跃数百个像素(尽管我看不到类似的东西)视觉上发生)。我需要该值是可预测的,以便在自动滚动过程中用户抓住滚动条或旋转鼠标滚轮时可以取消动画。

这是一个可以平滑滚动动画的函数:

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

下面是一个更复杂的版本,它将在用户交互时取消动画,并重新触发直到达到目标值,这在尝试即时设置scrollTop时非常有用(例如,简单地调用$(window).scrollTop(1000),根据我的经验,这无法解决50%的时间。)

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

在其他示例中,刷新页面后,我总是遇到动画总是从页面顶部开始的问题。

我通过不直接对CSS设置动画,而是window.scrollTo();在每个步骤上调用来解决此问题:

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

由于它使用跨浏览器JavaScript,因此也解决了htmlvs body问题。

请参阅http://james.padolsey.com/javascript/fun-with-jquerys-animate/,以获取有关可以使用jQuery的动画功能的更多信息。


5

您可以将jQuery动画用于具有特定持续时间的滚动页面:

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

其中1024px是滚动偏移量,而5000是动画的持续时间(以毫秒为单位)。


好答案!很高兴您加入了工期选项。只是想补充一点$("html, body").animate({scrollTop: 1024}, 5000);也可以。
瑞安·泰勒


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

1

如果您想向下移动到页面的末尾(因此您无需向下滚动到底部),可以使用:

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

0

但是,如果您真的想在滚动时添加一些动画,可以尝试使用我的简单插件(AnimateScroll),该插件目前支持30多种缓动样式


-3

跨浏览器代码为:

$(window).scrollTop(300); 

它没有动画,但无处不在


6
我在寻找一种“用jQuery动画scrollTop的方法?” “没有动画”的答案不是答案。
布莱恩·菲尔德
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.