jquery колесико мыши: обнаружение, когда колесо останавливается?

Я использую плагин Jquery MouseWheel, и я хотел бы иметь возможность определить, когда пользователь закончил использовать колесо. Функциональность, аналогичная остановке: событие в перетаскиваемом материале. Может ли кто-нибудь указать мне правильное направление?

5 ответов

Решение

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

Однако вы можете определить, когда пользователь не использовал его, скажем, за 250 мс, например:

$("#myElem").mousewheel(function() {
  clearTimeout($.data(this, 'timer'));
  $.data(this, 'timer', setTimeout(function() {
     alert("Haven't scrolled in 250ms!");
     //do something
  }, 250));
});

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

Чтобы завершить ответ Ника Крейвера:

var wheeldelta = {
  x: 0,
  y: 0
};
var wheeling;
$('#foo').on('mousewheel', function (e) {
  if (!wheeling) {
    console.log('start wheeling!');
  }

  clearTimeout(wheeling);
  wheeling = setTimeout(function() {
    console.log('stop wheeling!');
    wheeling = undefined;

    // reset wheeldelta
    wheeldelta.x = 0;
    wheeldelta.y = 0;
  }, 250);

  wheeldelta.x += e.deltaFactor * e.deltaX;
  wheeldelta.y += e.deltaFactor * e.deltaY;
  console.log(wheeldelta);
});

прокрутка выходов:

start wheeling!
Object {x: -1, y: 0}
Object {x: -36, y: 12}
Object {x: -45, y: 12}
Object {x: -63, y: 12}
Object {x: -72, y: 12}
Object {x: -80, y: 12}
Object {x: -89, y: 12}
Object {x: -97, y: 12}
Object {x: -104, y: 12}
Object {x: -111, y: 12}
Object {x: -117, y: 12}
Object {x: -122, y: 12}
Object {x: -127, y: 12}
Object {x: -131, y: 12}
Object {x: -135, y: 12}
Object {x: -139, y: 12}
Object {x: -145, y: 12}
Object {x: -148, y: 12}
Object {x: -152, y: 12}
Object {x: -154, y: 12}
Object {x: -156, y: 12}
Object {x: -157, y: 12}
Object {x: -158, y: 12}
Object {x: -159, y: 12}
Object {x: -161, y: 12}
Object {x: -162, y: 12}
Object {x: -164, y: 12}
Object {x: -166, y: 12}
Object {x: -167, y: 12}
Object {x: -169, y: 12}
stop wheeling!

Вот как это сделать на нативном JavaScript:

var _scrollTimeout = null;

function onMouseWheel() {
    var d = ((typeof e.wheelDelta != "undefined") ? (-e.wheelDelta) : e.detail);
    d = 100 * ((d>0)?1:-1);

    console.log("Scroll delta", d);

    clearTimeout(_scrollTimeout);
    _scrollTimeout = setTimeout(function() {
        console.log("Haven't scrolled in 250ms");
    }, 250);
}

window.addEventListener( 'mousewheel', onMouseWheel, false );
window.addEventListener( 'DOMMouseScroll', onMouseWheel, false ); // firefox

Вот как реализовать свое собственное событие остановки колеса.

//initialise the new variables
var wheelMap = new Map;
var deltaXEnded = false;
var deltaYEnded = false;
var previousSwipe = Object;
    previousSwipe.timeStamp = 0;
    previousSwipe.deltaX = 0;
    previousSwipe.deltaY = 0;
var wheelstart = false;

создать новый eventListener для события wheeltop

который мы будем вызывать из normalWheelEventCallbackFunction()

var wheelstop = new Event("wheelstop");

далее мы определим обратный вызов в случае отправки этого события и затем добавим событие к объекту окна.

function wheelstopcallback(event){
    wheelstart = false;
    console.log("wheel event has ended");
}
window.addEventListener("wheelstop", wheelstopcallback.bind(this));

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

window.addEventListener("wheel", normalWheelEventCallbackFunction.bind(this));

Функция обратного вызова события колеса

function normalWheelEventCallbackFunction(event){
   if(previousSwipe.timeStamp !== 0){
      if(event.timeStamp - previousSwipe.timeStamp < 1000)
         wheelMap.set(event.timeStamp, event);
      else
         wheelMap.clear();
   }
 else{previousSwipe.timeStamp = event.timeStamp;}


  if(event.deltaX > 2 && event.deltaX > previousSwipe.deltaX){
     //forward
     wheelstart = true
  }
  else if(event.deltaX < -2&& event.deltaX < previousSwipe.deltaX){
     //backward
     wheelstart = true;
  }
  else if(event.deltaY > 2 && event.deltaY > previousSwipe.deltaY){
     wheelstart = true;
  }
  else if(event.deltaY < 2 && event.deltaY < previousSwipe.deltaY){
     wheelstart = true;
  }

  if(
     ((event.deltaX === 1 || event.deltaX === 0 || event.deltaX === -1) && ((event.deltaX > 0 && event.deltaX < previousSwipe.deltaX) || (event.deltaX < 0 && event.deltaX > previousSwipe.deltaX)) && wheelstart)
     || (wheelstart && (event.deltaX === 0 && previousSwipe.deltaX === 0))
  )
  {
     deltaXEnded = true;
     console.log("deltaXEnded");
  }
  if(
     (((event.deltaY === 1 || event.deltaY === 0 || event.deltaY === -1) && ((event.deltaY > 0 && event.deltaY < previousSwipe.deltaY) || (event.deltaY < 0 && event.deltaY > previousSwipe.deltaY))) && wheelstart)
     || (wheelstart && (event.deltaY === 0 && previousSwipe.deltaY === 0)))     {
        deltaYEnded = true;
        console.log("deltaYEnded");
     }

     if(deltaXEnded && deltaYEnded){
        deltaXEnded = false;
        deltaYEnded = false;
        window.dispatchEvent(wheelstop);
     }

  previousSwipe.deltaX = event.deltaX;
  previousSwipe.deltaY = event.deltaY;
}

в этом может быть несколько ошибок, но по большей части логика довольно здравая, я бы порекомендовал сделать запасной вариант, если вам необходимо отследить каждое отправленное событие колеса, так как оно может иметь некоторые после отправки события 'wheeltop'.

о, и наконец, убедитесь, что реализовали обработчик, если он прерывается событием click, которое, следовательно, завершает событие wheel...

function wheelstopdispatch(){
  if(wheelstart)
    window.dispatchEvent(wheelstop);
  }
window.addEventListener("click", wheelstopdispatch);

Ответ Ника Крейвера работает отлично. Но это приведет к небольшой задержке (250 мс) для выполнения // do something, Лучшим вариантом было бы выполнить ваши коды сразу и ждать delayмс, прежде чем ловить дальнейшие события.

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

window.processing = false;
$("#myElem").mousewheel(function() {
   if (processing === false) {
     processing = true;
     // do something
     setTimeout(function() {
       processing = false;
     }, 250)); // waiting 250ms to change back to false.
   }
 });
Другие вопросы по тегам