jquery scrolltop() returns value of previous scrol

2019-08-10 21:07发布

I am using jquery function element.scrollTop() to get the current scroll position of the page using following line:

var currentScrollPosition=  $('html').scrollTop() || $('body').scrollTop();

But it always return a value of previous scroll position. Please check the code below (which is same as is in here). As you can try yourself and see in the code, after each tiny scroll, we get following series of values:

(1: when code is first run and no move is made yet)

delta:0

cumulativeDelta:0

functionCallCount:0

currentScrollPosition:0

(delta gives how much is scrolled, cumulativeDelta gives total amount of scroll, functionCallCount is how many times you scrolled and currentScrollPosition is value returned by scrolltop() )

(2: when scrolled a little)

delta:-120

cumulativeDelta:-120

functionCallCount:1

currentScrollPosition:0

(note here, currentScrollPosition is still not updated)

(3: when scrolled a little further)

delta:-120

cumulativeDelta:-240

functionCallCount:2

currentScrollPosition:90.90908893868948

(here, cumulativeDelta, which is addition of total scroll made so far, is doubled and currentScrollPosition is updated for the first time)

(4: when scrolled a little more)

delta:-120

cumulativeDelta:-360

functionCallCount:3

currentScrollPosition:181.81817787737896

(now, cumulativeDelta is tripled while currentScrollPosition is doubled. Hence, this is value after two scrolls but is updated adter 3 scrolls)

I apologize for long question, but would have been difficult to ask otherwise. I would like to know why is this happening and if I should use this function some other way there are any alternative to this function.

document.addEventListener("mousewheel", MouseWheelHandler);
var cumulativeDelta = 0,
  functionCallCount = 0;

function MouseWheelHandler(e) {
  e = window.event || e; // 'event' with old IE support
  var delta = e.wheelDelta || -e.detail; // get delta value

  cumulativeDelta += delta;
  functionCallCount += 1;
  currentScrollPosition = $('html').scrollTop() || $('body').scrollTop();

  document.getElementById("info1").innerHTML = "delta:" + delta;
  document.getElementById("info2").innerHTML = "cumulativeDelta:" + cumulativeDelta;
  document.getElementById("info3").innerHTML = "functionCallCount:" + functionCallCount;
  document.getElementById("info4").innerHTML = "currentScrollPosition:" + currentScrollPosition;

}
body {
  height: 2000px;
  border: solid red 3px;
}
.normalPart {
  border: solid green 2px;
  height: 900px;
}
.stationary {
  position: fixed;
  top: 0px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.0/jquery.min.js"></script>
<div class="stationary">
  <div id="info1"></div>
  <div id="info2"></div>
  <div id="info3"></div>
  <div id="info4"></div>
</div>

1条回答
Evening l夕情丶
2楼-- · 2019-08-10 21:33

The issue is because the mousewheel event fires when the mousewheel movement starts. You are reading the scrollTop at the point before the update has happened. You need to use a timer to get the scrollTop after the mouse wheel scroll has finished. Try this:

document.addEventListener("mousewheel", MouseWheelHandler);
var cumulativeDelta = 0,
    functionCallCount = 0,
    currentScrollPosition = 0;

function MouseWheelHandler(e) {
    e = window.event || e; // 'event' with old IE support
    var delta = e.wheelDelta || -e.detail; // get delta value

    cumulativeDelta += delta;
    functionCallCount += 1;

    setTimeout(function() {
        currentScrollPosition = $(window).scrollTop();
        document.getElementById("info4").innerHTML = "currentScrollPosition:" + currentScrollPosition;
    }, 200); // update currentScrollPos 200ms after event fires

    document.getElementById("info1").innerHTML = "delta:" + delta;
    document.getElementById("info2").innerHTML = "cumulativeDelta:" + cumulativeDelta;
    document.getElementById("info3").innerHTML = "functionCallCount:" + functionCallCount;
}
body {
  height: 2000px;
  border: solid red 3px;
}
.normalPart {
  border: solid green 2px;
  height: 900px;
}
.stationary {
  position: fixed;
  top: 0px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.0/jquery.min.js"></script>
<div class="stationary">
  <div id="info1"></div>
  <div id="info2"></div>
  <div id="info3"></div>
  <div id="info4"></div>
</div>

Alternatively you could read the currentScrollTop position directly on the scroll event of the window as that will always be in sync with its current position.

查看更多
登录 后发表回答