使用scrollTop的奇怪行为

时间:2014-01-24 15:13:25

标签: javascript jquery

我使用scrollTop JQuery函数有一种奇怪的行为。我有一个div包含一个复杂的文本,分为不同的部分,如下所示:

<div id="wrapper" ... >
    <div id="section1">
        <h1>Section 1</h1>
        Lorem ipsum dolor sit amet, consectetuer... 
        ...
    </div>
    <div id="section2">
        <h1>Section 2</h1>
        Lorem ipsum dolor sit amet, consectetuer... 
        ...
    </div>
    <div id="section3">
        <h1>Section 3</h1>
        Lorem ipsum dolor sit amet, consectetuer... 
        ...
    </div>
    ...

第二个DIV包含一个简单的部分列表,当用户点击每个部分时,我想在右侧部分滚动包装:

<li>
   <a href="#" onclick="customScrollTo('section1')">section1</a>
</li>
<li>
   <a href="#" onclick="customScrollTo('section2')">section2</a>
...

这是JS函数的简单:

function customScrollTo (section) {

     $('#wrapper').animate({
         scrollTop: $("#wrapper div[id='" + section + "']").offset().top
     }, 200);
};

现在如果您尝试在此JSfiddle中测试它: http://jsfiddle.net/Ws5F9/4/

你可以看到两个奇怪的行为:

  1. 如果您点击“第1部分”而不是“第2部分”而非“第3部分”,则第3部分无效!
  2. 如果您在同一部分链接上点击两次,则第二次在页面顶部滚动

3 个答案:

答案 0 :(得分:4)

customScrollTo方法存在两个问题。

首先,您使用.offset()代替.position()。这将返回相对于文档而不是#wrapper div的位置。这里几乎没有引起注意,因为无论如何div都接近文档的顶部,但是当你将它向下移动到页面上时,你会遇到麻烦。

其次,当您调用position时,它将返回元素的位置,并考虑当前滚动位置,因此如果您已经滚动到文档的顶部,它将作为预期,但任何进一步滚动都会导致麻烦,因为文档已被移动。您需要将当前滚动位置添加到最终滚动值中,以便它不会“丢失”。

以下是解决这两个问题的示例:

function customScrollTo (section) {

     $('#wrapper').animate({
         scrollTop: $("#wrapper div[id='" + section + "']").position().top + $("#wrapper").scrollTop()
     }, 200);
 };

答案 1 :(得分:3)

使用此:

function customScrollTo (sectionId) {
    var $wrapper = $('#wrapper'),
        $section = $('#' + sectionId);
     $wrapper.animate({
         scrollTop: $wrapper.scrollTop() + $section.position().top
     }, 200);
 }

.offset()函数获取相对于文档的坐标,而.position()函数获取相对于父文档的坐标。但是.position().top值随着元素的滚动而改变。添加父级.scrollTop()值可以进行调整。

jsfiddle

答案 2 :(得分:0)

试试这个,我也修改了你的标记。见 DEMO

$('#index ul').on('click', 'a', function(e) {
 var section = $(this).prop('href');
 section = section.split('#')[1];
 var top = $("#" + section)[0].offsetTop;

 $('#wrapper').stop().animate({
     scrollTop: top
 }, 200);
 return false;
 });