I'm using Jquery mousewheel plugin and I would like like to be able to detect when the user has finished using the wheel. Similar functionality as the stop: event in the draggable stuff. Can somebody point me to the right direction?
问题:
回答1:
There's no "stop" event here really - you get an event when you do scroll, so every time a mousewheel event happens the event is triggered...when there's nothing you'll get no events and your handler won't be firing.
You ca however detect when the user hasn't used it in say 250ms, like this:
$("#myElem").mousewheel(function() {
clearTimeout($.data(this, 'timer'));
$.data(this, 'timer', setTimeout(function() {
alert("Haven't scrolled in 250ms!");
//do something
}, 250));
});
You can give it a try here, all we're doing is storing the timeout on each use in using $.data()
, if you use it again before that time runs out, it gets cleared...if not then whatever code you wanted to run fires, the user has "finished" using their mousewheel for whatever period of time you're testing for.
回答2:
To complete Nick Craver's answer:
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);
});
scrolling outputs:
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!
回答3:
Here's how to do it in native 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
回答4:
Here's how to implement your own wheel stop event.
//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;
make a new eventListener for the wheelstop event
which we will be calling from the normalWheelEventCallbackFunction()
var wheelstop = new Event("wheelstop");
next we will define the callback in the case of this event being dispatched & then add the event to the window object.
function wheelstopcallback(event){
wheelstart = false;
console.log("wheel event has ended");
}
window.addEventListener("wheelstop", wheelstopcallback.bind(this));
now we define the normal wheel event listener as well as define the callback this listener will be using...
window.addEventListener("wheel", normalWheelEventCallbackFunction.bind(this));
The Wheel Event Callback Function
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;
}
this may have a few mistakes, but for the most part the logic is pretty sound, I would recommend a fallback however if you are required to catch every single wheel event dispatched since it may have some after the 'wheelstop' event has been dispatched.
oh and lastly be sure and implement a handler for if it is interrupted by the click event which consequently ends the wheel event...
function wheelstopdispatch(){
if(wheelstart)
window.dispatchEvent(wheelstop);
}
window.addEventListener("click", wheelstopdispatch);
回答5:
Nick Craver's answer works fine. But it will cause a small delay (of 250ms) to perform the // do something
. A better option would be to execute your codes right away and wait delay
ms before catching further events.
To do this, use a global variable say processing
, initialize it with false
and toggle it's value before and after code execution.
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.
}
});