Подтвердить что ты не робот

Обнаруживать, запускается ли событие прокрутки вручную в 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 не может правильно определить триггер анимации.

Есть ли другой способ сделать это?

4b9b3361

Ответ 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
  }
});

Конечно, технически, если пользователь решит прокрутить вручную во время анимации, это также не вызовет логику при прокрутке, но этого достаточно, чтобы не беспокоиться.