neaumusic
neaumusic

Reputation: 10454

Determine user scroll vs JavaScript scrollTop change

How can I determine if a scroll event was caused by my own animation, or it was caused by a user's scroll?


I have a scrollable area, which acts like a CV control knob, where the user can scroll and directly map to a DOM element's size, left, and top

If a scroll event ends inside specific bounds, I want to "snap" to a nearby position, with a granular tween that modifies the same scrollable area's scrollTop.

While this transition is occurring, I want any user scroll to immediately override the animation, so that the user regains control


I feel like I'm very close to a solution, and I noticed that my usecase involves floating point increments, where a user scroll will only increase by full integers. I'm not sure if this is useful, and it feels like a hack to abuse, but I'm really looking for ANY WAY that I can discriminate between a user scrollTop change, and my animation's scrollTop change

Upvotes: 4

Views: 1749

Answers (2)

neaumusic
neaumusic

Reputation: 10454

The answer is to keep track of the delta scroll distance added and what the scrollTop should be.

If the browser polls for scrollTop and emits a scroll event, you need to compare that scrollTop with your intended addition, or whatever scrollTop is supposed to be. You can also pursue listening for "wheel" rather than scroll


The biggest problem for me was that scrollTop cannot have floating point numbers, and setting scrollTop to 150.999 is the same as setting 150, so I recommend Math.round() beforehand, and checking the scroll Math.abs(event.target.scrollTop - myScrollTop) < 1 or some similar comparison, since myScrollTop is still the correct, floating point (non-integer) number


Also worth mentioning is that zooming and changing the CSS reference pixel (window.devicePixelRatio) seems to affect scrollTop ingestion or emission

Right now, my scroll behavior breaks if I use CMD+ or CMD-, but I will deal with this shortly

Upvotes: 0

shubham agrawal
shubham agrawal

Reputation: 3541

I was stuck at something I was doing in my project and I needed to detect whether user is scrolling or is it that our code that is scrolling.I used a global variable myVar which changes its value depending on scroll events. FIDDLE

Here is the code.

var myVar = false;
$("#button").click(function() {
  myVar = true;
  $('html, body').animate({
    scrollTop: $("#bottom").offset().top
  }, 2000);
});
$(window).bind('mousewheel DOMMouseScroll', function(event) {
  myVar = false;
});
$(document).scroll(function() {
  console.log('Scroll initiated by ' + (myVar == true ? "user" : "browser"));
});
div:hover {
  text-decoration: underline;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<span> hello there </span>
<br/>
<div id="button"> click here to go down </div>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<div id="bottom"> just sitting </div>

Upvotes: 1

Related Questions