Reputation: 10454
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
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
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