我想平滑地向下滚动。我不想为此写一个函数——特别是如果jQuery已经有了一个。


当前回答

就像Kita提到的有多个回调发射的问题,当你在“html”和“身体”动画。我更倾向于使用一些基本的特征检测,只对单个对象的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。 相反,我找到了一种方法,使用承诺做一个单一的回调每次动画执行。

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

其他回答

你可以使用.animate() scrollTop属性,就像这样:

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

我有什么我相信是一个更好的解决方案比$('html,身体')黑客。

这不是一行程序,但我用$('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);
                    }
                }
            }
        );
    }
}

就像Kita提到的有多个回调发射的问题,当你在“html”和“身体”动画。我更倾向于使用一些基本的特征检测,只对单个对象的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。 相反,我找到了一种方法,使用承诺做一个单一的回调每次动画执行。

$('html, body')
    .animate({ scrollTop: 100 })
    .promise()
    .then(function(){
        // callback code here
    })
});
$(".scroll-top").on("click", function(e){
   e.preventDefault();
   $("html, body").animate({scrollTop:"0"},600);
});

试试scrollTo插件。