Обнаруживать, запускается ли событие прокрутки вручную в jQuery
Этот вопрос уже задавался здесь давно:
Обнаружение триггера события jquery пользователем или вызов по коду
Но на него никогда не отвечали окончательно (или, может быть, я просто не мог правильно искать).
Можно ли определить, было ли инициировано событие scroll
пользователем или функцией jQuery animate
?
Я пытаюсь предотвратить событие scroll
для запуска самого себя, выполняя что-то вроде этого:
$(document).scroll(function(){
$("html").stop(true);
var number = 400; //some other stuff is happening here
clearTimeout(tout);
tout = setTimeout(function(){
if(top == $(document).scrollTop()){
$("html").animate({
scrollTop: (number),
easing: "easeInQuad",
duration: 110
});
}
},120);
});
Этот код кажется подходящим:
$('#scroller').scroll(function(e) {
if (e.originalEvent) {
console.log('scroll happen manual scroll');
} else {
console.log('scroll happen by call');
}
});
Но объект originalEvent
не может правильно определить триггер анимации.
Есть ли другой способ сделать это?
Ответы
Ответ 1
Может быть, селектор :animated
поможет вам:
$('#scroller').scroll(function(e) {
if ($(this).is(':animated')) {
console.log('scroll happen by animate');
} else if (e.originalEvent) {
// scroll happen manual scroll
console.log('scroll happen manual scroll');
} else {
// scroll happen by call
console.log('scroll happen by call');
}
});
Демо
Ответ 2
Я не знаю, насколько хорошо это работает с сенсорными экранами, но это работает для меня на рабочем столе по крайней мере
$(window).on('mousewheel', function(){
//code that will only fire on manual scroll input
});
$(window).scroll(function(){
//code that will fire on both mouse scroll and code based scroll
});
Я не думаю, что есть способ ориентироваться только на анимированный свиток (принятый ответ мне не помог).
ОБНОВЛЕНИЕ: Предупреждение!
К сожалению, 'mousewheel'
, похоже, не подходит для пользователей, которые вручную захватывают полосу прокрутки и перетаскивают ее или пользователей, которые используют кнопки со стрелками: (
Это все еще работает нормально для устройств с сенсорным экраном, так как их звуки выглядят как свитки мыши. Однако это не отличное решение для настольных пользователей.
Ответ 3
Используя принятый ответ @Tony и комментарий @DanielTonon, я придумал следующее решение:
var animatedScroll = false;
var lastAnimatedScroll = false;
$(window).scroll(function(event){
lastAnimatedScroll = animatedScroll;
animatedScroll = $('html, body').is(':animated');
});
Это, похоже, решает проблему, в которой jquery удаляет .is(':animated')
, затем прокручивает еще один пиксель, что приводит к .is(':animated')
, заканчивающемуся на false. Сохраняя от второй до последней версии .is(':animated')
, вы можете быть увереннее, была ли прокрутка анимированной или нет.
Если вы хотите узнать, была ли анимирована прокрутка или не просто проверить переменную lastAnimatedScroll
.
Это НЕ было полностью проверено мной, но было исправлено во многих обновлениях страницы, поэтому я предполагаю, что он работает достаточно хорошо.
Ответ 4
Я бы предложил сначала создать функцию javascript
// Attaching scroll event when document/window is loaded
function OnFirstLoad() {
if (document.attachEvent) {
document.attachEvent('onscroll', scrollEvent);
} else if (document.addEventListener) {
document.addEventListener('scroll', scrollEvent, false);
}
}
тогда используйте
window.onload = OnFirstLoad;
или
$(document).ready(function () {
OnFirstLoad();
});
В этом событии прокрутки есть функция
function scrollEvent(e) {
var body = document.body,
html = document.documentElement;
var docHeight = Math.max(body.scrollHeight, body.offsetHeight,
html.clientHeight, html.scrollHeight, html.offsetHeight);
var currentScroll = (document.documentElement && document.documentElement.scrollTop) || document.body.scrollTop;
// implement your logic according to requirement
}
Ответ 5
После попытки реализовать различные решения в этом вопросе, я предложил другой подход, который хорошо работает для меня.
Я использую ручное логическое выражение для запуска анимации:
var isRunningAnimation = false;
и установите его в true
непосредственно перед анимацией, и false
в функции обратного вызова jQuery animate
:
isRunningAnimation = true;
$('html').animate({
scrollLeft: 100,
scrollTop: 100
}, 400, 'swing', function() {
isRunningAnimation = false;
});
а затем в прослушивателе прокрутки просто проверьте, что логическое:
$('scroll', function() {
if (!isRunningAnimation) {
// If we made it to here, the animation isn't running
}
});
Конечно, технически, если пользователь решит прокрутить вручную во время анимации, это также не вызовет логику при прокрутке, но этого достаточно, чтобы не беспокоиться.