Opera 错误上的 jQuery 动画滚动顶部

Posted

技术标签:

【中文标题】Opera 错误上的 jQuery 动画滚动顶部【英文标题】:jQuery animate scrolltop on Opera bug 【发布时间】:2011-06-20 07:49:57 【问题描述】:

有人用过吗

$(“html, body”).animate(scrollTop:0, 'slow');

在 Opera 浏览器上?

它会产生一种奇怪的效果,尤其是当您在长页面上滚动时,似乎页面先到顶部,然后再向下滚动到正确的位置。这是一种奇怪的令人不安的效果......

有什么办法可以解决吗?谢谢

【问题讨论】:

@caamel 考虑创建一个演示(例如在 jsfiddle 中) 不需要在窗口上应用scrollTop()吗?我认为这是正确的做法。 【参考方案1】:

过去没有正确定义该属性。我认为它是由 IE 引入的,然后进行逆向工程以由不同的用户代理实现。它已经在CSSOM 中进行了描述(仍然是一个工作草案)。到今天为止,Opera 中确实还有一个 bug,正在修复中。

## 可能的黑客攻击。

解决办法是

$(window.opera?'html':'html, body').animate( 
  scrollTop:0, 'slow' 
);

要小心,因为如果 Opera 在某个时间点修复它,代码可能会表现得很奇怪。

为什么?

在 Firefox 和 IE quirks 模式下,您必须在“body”上设置该属性才能使页面滚动,而如果您在“html”上设置该属性,则会被忽略。 在 Firefox 和 IE 标准模式下,您必须在“html”上设置该属性才能使页面滚动,而如果您在“body”上设置该属性,则会被忽略。 在 Safari 和 Chrome 中,无论是哪种模式,您都必须在“body”上设置该属性以使页面滚动,而如果您在“html”上设置该属性,则会被忽略。

由于页面处于标准模式,他们必须在“html”和“body”上都设置它,否则它将无法在 Safari/Chrome 中运行。

现在是坏消息;在 Opera 中,当您读取正文的 scrollTop 时,它正确为 0,因为正文在文档中不可滚动。但如果您在“html”或“body”上设置滚动偏移量,Opera 将滚动视口。结果,动画设置了两个属性,一个用于“html”,一个用于“body”。第一个从正确的位置开始,而第二个从 0 开始,导致闪烁和奇怪的滚动位置。

不涉及用户代理嗅探的更好解决方案

来自http://w3fools.com/js/script.js

    // find out what the hell to scroll ( html or body )
    // its like we can already tell - spooky
    if ( $docEl.scrollTop() ) 
        $scrollable = $docEl;
     else 
        var bodyST = $body.scrollTop();
        // if scrolling the body doesn't do anything
        if ( $body.scrollTop( bodyST + 1 ).scrollTop() == bodyST) 
            $scrollable = $docEl;
         else 
            // we actually scrolled, so, er, undo it
            $body.scrollTop( bodyST - 1 );
        
    

【讨论】:

【参考方案2】:

这个http://www.zachstronaut.com/posts/2009/01/18/jquery-smooth-scroll-bugs.html#opera 可能是一个更好的解决方案,无需使用任何 Opera 特定功能并考虑怪癖模式。

【讨论】:

【参考方案3】:
$("body:not(:animated)").animate( scrollTop: destination, 500 );
return false;

为我工作,在歌剧中也是如此。

编辑:虽然在 Firefox 中不起作用

【讨论】:

【参考方案4】:

我也遇到过这个问题。这就是我使用的并且有效。这不是浏览器嗅探,但对我来说这不是特别好的代码。现在可以了。

在 Opera 11 / IE 8 / FF 3.6 的 html 元素上调用 scrollTop 会返回一个大于零的数字

在 Chrome 10 / Flock 3.5 / Safari 5(适用于 Windows)中的 html 元素上调用 scrollTop 返回 0

所以只需测试一下:

如果浏览器是 Opera,则在 scrollTop 上测试大于 0 的数字,然后仅在 html 上调用 scrollTop,一个 la

var html = document.getElementsByTagName('html')[0];

var body = document.getElementsByTagName('body')[0];

$(html).animate(scrollTop:0+'px','duration':1000,'easing':'swing');

如果浏览器是 Chrome、Flock 或 Safari,那么 scrollTop 将返回 0 并且您对此进行测试,并采取相应措施:

$(html,body).animate(scrollTop:0+'px','duration':1000,'easing':'swing');

因此,您将为标准模式 FF 和 IE 设置对 html 的效果(也应涵盖怪癖。呃),并为 Chrome 和 Safari 设置正文。

在尝试滚动 html 和 body 的 Opera 中,从而导致大量怪异,scrollTop 返回一个大于 0 的数字,因此您只调用 html 并且您不会得到闪烁的废话。

所以你可以在必要时安全地使用 html 和 body,或者当浏览器是 Opera 时只使用 html。

并且不要忘记您的 preventDefault() ,否则您将不得不担心这将是另一个奇怪的闪烁。 ;)

嘿,我不是 JS 忍者,但我很努力,这对我有用,而且我现在没有时间尽可能多地调查它,所以我想我会发布这个在这里和帮助。如果我错了,我会举起双手说出来。 ;) 所以请反馈。 :D

汤姆。

【讨论】:

【参考方案5】:

是的! 我在click() 函数中调用animate(scrollTop: ) 函数时遇到问题。

最好的方法是http://www.zachstronaut.com/posts/2009/01/18/jquery-smooth-scroll-bugs.html#opera,这里是Divya Manian写的。

在开始滚动事件之前,需要在调用滚动函数或动画函数之前使用event.preventDefault()来结束点击事件。

类似这样的:

$(<clicked_element>).click(function(event)
    event.preventDefault();
    $('html, body').animate(scrollTop: <value>, 600);
);

编辑:将滚动方法应用于$('html, body') 元素很重要

【讨论】:

以上是关于Opera 错误上的 jQuery 动画滚动顶部的主要内容,如果未能解决你的问题,请参考以下文章

aos.js超赞页面滚动元素动画jQuery动画库

使用 jQuery 动画 scrollTop 总是从顶部开始

动画 jQuery 滚动顶部

jquery 动画滚动顶部回调

如何在不将页面滚动条重置为顶部的情况下使用 jQuery 为固定 div 设置动画

javascript 滚动偏移上的导航顶部动画