Сделать изменения "scrollLeft" / "scrollTop" не запускать прослушиватель событий прокрутки
14 Matchu [2009-09-06 23:51:00]
В настоящее время моя программа находится в месте, где он одновременно слушает, что пользователь прокручивает определенный элемент, но также порой автоматически прокручивает этот элемент сам по себе. (Не постепенный, симпатичный свиток, но мгновенный прыжок. Это имеет смысл в контексте, клянусь.)
Есть ли способ сделать событие прокрутки не срабатывающим, если прокрутка была выполнена путем установки scrollLeft или scrollTop? Моя первая мысль была основным переключателем, например:
ignoreScrollEvents = true;
element.scrollLeft = x;
ignoreScrollEvents = false;
function onScroll() {
if(ignoreScrollEvents) return false;
}
но поскольку события не запускаются немедленно (oops, duhh), это не выполнимое решение. Какие еще ответы я мог бы попробовать? Я также использую jQuery, если это что-то помогает.
javascript jquery html
5 ответов
16 Решение Shog9 [2009-09-07 00:19:00]
Самый простой общий метод? Просто reset флаг в обработчике событий. Сначала вы захотите проверить, действительно ли вы меняете значение, так как иначе событие не будет запущено - как отмечает Родриго, хорошая практика здесь заключается в том, чтобы вытесните это так называемые "сеттерные" функции:
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;
...
}
2 Rodrigo [2009-09-07 00:21:00]
Как насчет сеттера?
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; }
<button onclick=setScrollTop(1000)>Random scrollTop</button>
<button onclick=setScrollLeft(1000)>Random scrollLeft</button>
1 marcgg [2009-09-07 00:10:00]
Вы можете постоянно проверять, если позиция прокрутки изменения...
0 Colin [2009-09-07 00:18:00]
Вы можете попытаться сохранить верхнюю часть смещения вашего элемента и сопоставить его с 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
}
}
0 Matchu [2009-09-07 00:53:00]
Хорошо, мое окончательное решение, построив 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, не устанавливают флаг неверно.
Спасибо, все!