问题
I've tried to implement a page panorate by dragging. In my implementation the page moves for a while after user has released the mouse button, like dragging maps in Google Maps. Now I'd like to prevent this effect, when the mouse is no longer moving when user releases the button. The problem is, that I just can't figure out how to detect if the mouse really moves when mouseup event is fired.
For now I've tried to tackle this problem by calculating the dragging speed and then compare the speed to a pre-valued "sensitivity", which works most of the time, but sometimes it fails.
Simplified example at jsFiddle . When playing around with the fiddle, please use middlebutton in FF, the draggabble div "sticks" to the left button.
Pseudocode:
AniMove = function (doc, element, sensitivity, panspeed, duration) {
var mouseDown = function (e) {
sTime = new Date();
originalX = mouseX = e.clientX;
originalY = mouseY = e.clientY;
/* addEventListeners mousemove & mouseup for document */
return;
},
mouseMove = function (e) {
/* Setting new position for #square + new mouseX & Y */
return;
},
mouseUp = function () {
var dc = 1;
/* removeEventListeners mousemove & mouseup */
eTime = new Date();
vX = Math.round((50 * panspeed) * (originalX - mouseX) / (eTime - sTime));
vY = Math.round((50 * panspeed) * (originalY - mouseY) / (eTime - sTime));
// Check whether mouse is moving or not,
// now checking the speed against sensitivity, which is not reliable
if (Math.abs(vX) < sensitivity){vX = 0;}
if (Math.abs(vY) < sensitivity){vY = 0;}
for (n = 0; n < dur; n++, dc += 0.001) {
vX = Math.round(vX * dec / dc);
vY = Math.round(vY * dec / dc);
delay[n] = setTimeout(endDrag(n, vX, vY), n * 50);
}
return;
},
endDrag = function (n, vX, vY) {
/* Setting new position for #square */
return;
},
dec = 1 - 120 / duration;
panspeed *= -0.01;
duration /= 50;
element.addEventListener('mousedown', mouseDown, false);
}
drag = new AniMove(document, document.getElementById('square'), 20, 100, 500);
So, is it even possible to detect if mouse is moving or not in this situation? Maybe I need a different approach for this task?
回答1:
One idea is keep the mouseMove listener active for .5 second after the mouseUp (set a timer), if the mouse has moved in that .5 second (i.e. mouse position is different from what it was at mouseUp) then assume there was motion and animate it.
You may need to play around with the .5 second to see what gives the best feel.
回答2:
You want the view to continue moving and gradually stop, right?
All you need to do is note how fast it was moving BEFORE the MouseUp event, then reduce the speed in increments over half a second or so. It should be irrelevant whether the mouse continues to move if the button is not down.
Once you have "let go of the ball" how fast it rolls is nothing to do with what your hand does next.
So, you need to track the mouse speed while the button is down, then just "fade out" once the button is up.
In your case, if the mouse was not moving when the button was released, the analogy is that the user has "held on to the ball". So it should stop straight away.
So you don't need to do anything special to handle that situation. If the user stops the mouse with the button down, stop panning.
来源:https://stackoverflow.com/questions/12175176/how-to-detect-if-mouse-is-moving-when-mouseup-is-fired