4

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

1
  • If you are using a framework (jQuery in particular) you could pass an argument to the .trigger() call. This call would be present in code-made calls, but absent from event calls. Commented Mar 2, 2017 at 5:28

2 Answers 2

1

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>

Sign up to request clarification or add additional context in comments.

Comments

0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.