Сделать изменения «scrollLeft» / «scrollTop» не запускать прослушиватель событий прокрутки

В настоящее время моя программа находится в месте, где он одновременно слушает, что пользователь просматривает определенный элемент, но также порой автоматически прокручивает этот элемент сам по себе. (Не постепенный, симпатичный свиток, но мгновенный прыжок. Это имеет смысл в контексте, клянусь.)

Есть ли способ сделать событие прокрутки не срабатывающим, если прокрутка была выполнена путем установки scrollLeft или scrollTop? Моя первая мысль была основным переключателем, например:

ignoreScrollEvents = true; element.scrollLeft = x; ignoreScrollEvents = false; function onScroll() { if(ignoreScrollEvents) return false; } 

но поскольку события не срабатывают немедленно (oops, duhh), это не приемлемое решение. Какие еще ответы я мог бы попробовать? Я также использую jQuery, если это что-то помогает.

Самый простой общий метод? Просто сбросьте флаг в обработчике событий. Сначала вы захотите проверить, действительно ли вы меняете значение, поскольку в противном случае событие не будет запущено, как отмечает Родриго , хорошая практика здесь состоит в том, чтобы разделить это на так называемые «сеттерные» функции:

 function setScrollLeft(x) { if ( element.scrollLeft != x ) { ignoreScrollEvents = true; element.scrollLeft = x; } } ... function onScroll() { var ignore = ignoreScrollEvents; ignoreScrollEvents = false; if (ignore) return false; ... } 

Но, в зависимости от ваших потребностей, вы уже можете где-то хранить положение прокрутки; если да, просто обновите и проверьте это как свой флаг. Что-то вроде:

 element.scrollLeft = currentScrollLeft = x; ... function onScroll() { // retrieve element, etc... if (element.scrollLeft == currentScrollLeft) return false; ... } 

Как насчет сеттера?

 var _preventEvent = false; // set global flag function setScrollTop(amount) { _preventEvent = true; // set flag document.documentElement.scrollTop = amount * Math.random(); } function setScrollLeft(amount) { _preventEvent = true; // set flag document.documentElement.scrollLeft = amount * Math.random(); } // scroll event listener window.onscroll = function() { console.clear(); if (_preventEvent) { _preventEvent = false; // reset flag return; } console.log('normal scroll'); } 
 html{ height:500%; width:500%; } button{ position:fixed; } button + button{ top:50px; } 
   

Вы можете постоянно проверять, изменяется ли положение прокрутки …

Вы можете попытаться сохранить верхнюю часть смещения вашего элемента и сопоставить его с scrollTop, когда вы переходите внутрь onScroll:

 function onScroll(){ var scrollTop = (document.documentElement.scrollTop || document.body.scrollTop), offsetTop = $('selector').offset().top; if(offsetTop > scrollTop){ //user has not scrolled to element so do auto scrolling } } 

Хорошо, мое окончательное решение, построение Shog9 (не мой настоящий код, но мой подход):

 var oldScrollLeft = element.scrollLeft; element.scrollLeft = x; if(element.scrollLeft != oldScrollLeft) { ignoreScrollEvents = true; } function onScroll() { if(!ignoreScrollEvents) performGreatActions(); ignoreScrollEvents = false; } 

Оператор if устанавливает флаг игнорирования, когда значение scrollLeft действительно заканчивается изменением, поэтому случаи, такие как установка от 0 до 0, не устанавливают флаг неправильно.

Спасибо всем!