是否可以使用jQuery动画scrollTop?

Bry*_*eld 222 javascript jquery

我想顺利向下滚动.我不想为此编写一个函数 - 特别是如果jQuery已经有一个函数.

Nic*_*ver 460

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

$("html, body").animate({ scrollTop: "300px" });
Run Code Online (Sandbox Code Playgroud)

  • body由webkit使用,html由firefox使用. (28认同)
  • 为什么你需要`html`和`body`?这里有一些见解:http://stackoverflow.com/questions/2123690/slow-down-scroll-to-top-event-by-jquery-animate/2123721#comment16858893_2123721,但这不是一个完整的答案. (15认同)
  • 仅供参考:如果`<html>` 有`overflow-x:hidden;` 这个动画将不起作用。(可能不适用于 `overflow-y:hidden` 和 `overflow:hidden`,但我还没有测试过。 (2认同)

Kit*_*ita 73

尼克的回答非常好.在animate()调用中指定complete()函数时要小心,因为它会被声明两个选择器(html和body),因此会执行两次.

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

这是你如何避免双重回调.

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

  • 因为取决于您使用的是哪种浏览器,您可以为主体或html设置动画.通过动画两种方式,您可以覆盖更多浏览器. (21认同)

pat*_*der 26

尼克的答案非常好,默认设置很好,但您可以通过完成所有可选设置来更全面地控制滚动.

这是它在API中的样子:

.animate( properties [, duration] [, easing] [, complete] )
Run Code Online (Sandbox Code Playgroud)

所以你可以这样做:

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

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


Ste*_*hen 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...
    })
});
Run Code Online (Sandbox Code Playgroud)

更新 - - -

上述特征检测尝试失败.看起来像webkit类型的浏览器没有单行的方式.当存在doctype时,pageYOffset属性总是返回零.相反,我找到了一种方法,可以在每次动画执行时使用promise来执行单个回调.

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


Joh*_*war 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);
            }
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

下面是一个更复杂的版本,它将在用户交互时取消动画,并在达到目标值之前重新启动,这在尝试即时设置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);
                    }
                }
            }
        );
    }
}
Run Code Online (Sandbox Code Playgroud)


com*_*tic 7

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

我通过不直接动画css而是调用window.scrollTo();每一步来解决这个问题:

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

这也解决了htmlvs body问题,因为它使用跨浏览器JavaScript.

有关使用jQuery动画功能可以做些什么的更多信息,请查看http://james.padolsey.com/javascript/fun-with-jquerys-animate/.


Ale*_*ano 5

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

$("html, body").animate({scrollTop: "1024px"}, 5000);
Run Code Online (Sandbox Code Playgroud)

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