How to detect when mouse has stopped
Asked Answered
F

2

18

I have written the following JavaScript code. I am using it to detect when the mouse is moving and when it has stopped. MouseStopped() function is a loop of hundreds of items that will tell me where the mouse has stopped, so I want to call it only when the mouse has stopped.

var CheckMovement;
var stopLoop = false;
var n = 0;
canvas.addEventListener('mousemove', function (evt) {
    CheckMovement = setInterval(function () { HasMouseStopped(evt) }, 250);
}, false)

function HasMouseStopped(evt) {
    var mousePos = getMousePos(canvas, evt);
    newMouseX = mousePos.x;
    newMouseY = mousePos.y;
        if ((newMouseX !== mouseX) && (newMouseY !== mouseY)) {

            stopLoop = true;
        } else {
            //stopped moving
            clearInterval(CheckMovement);
            stopLoop = false;
            n = 0;
            MouseStopped();
        }
        mouseX = newMouseX;
        mouseY = mousePos.y;
}

function MouseStopped() {
    while (arr.length > n) {
        if (stopLoop) { break; }
        if (ctx.isPointInPath(mouseX, mouseY)) {
            //tooltip text
            ctx.font = '12pt Candara';
            ctx.fillStyle = 'black';
            ctx.fillText(arr[n], mouseX + 10, mouseY - 5);
            break;
        }
        n++;
    }
}

Now I have the following problems:

  1. Even though I am calling clearInterval(CheckMovement), it doesn't stop iterating; it is running continuously, which cause the problem of calling MouseStopped() multiple times. Why is it not stopping?
  2. I would like to break MouseStopped() in the middle of its operation if the mouse is moved before it completed its the loop. This is why I am setting stopLoop = true; However, that also doesn't seem to be working as intended. How can I achieve these?

Thanks.

EDITS

Fontaine answered 15/7, 2013 at 4:33 Comment(8)
You have a test inside a loop that cannot be set to true while the loop is running... while (arr.length > n) { if (stopLoop) { break; } - your mouseStopped also has to use setTimeout or interval to be interruptableToughminded
First, define when a mouse is considered stopped... Is it on inactive for 3 seconds, or 3 mils, one will hit significantly more than another| Second, set an interval function on mouse move, compare previous and current mouse location until they match and stop your interval functionAlgetic
use setTimeout insteadBuggs
Thanks, mplungjan, for the insight. I can rework this part.Fontaine
Loic, that could just do it. Thanks.Fontaine
Seth, I prefer to test inactive for one second; the loop also takes another second, so it rounds up to 2 seconds. But I wanted to check that inactivity every quarter of a second... The second part of your comment is what I think I am doing, am I getting it wrong?Fontaine
I think the question here is 'how to stop the loop the moment a movement is detected'. This is where I have a problem. I have tried to use timer but doesn't seem to work for me. The loop runs for 100ms, stops to check if mouse moved, then continues if there was no movement. Seems logical but really wasteful, and yet, I cant get that result anyway. Anyone with an idea how that can be constructed.Fontaine
@HanningtonMambo: Were you able to figure this out? If so, can you mark this post as answered (click the green check).Syllabogram
S
30

This can be done very simply: when the mouse is moved, set a timeout for n milliseconds in the future. Also, clear the last timeout to reset the time. Like the following listener.

let timer
canvas.addEventListener(`mousemove`, () => {
    clearTimeout(timer)
    timer = setTimeout(mouse_stopped, 300)
})

See this JSFiddle.

Syllabogram answered 9/10, 2013 at 3:22 Comment(0)
A
-1

After a little thinking, I think the debounce function may meet your needs. Lodash.js provides it.

Associate answered 6/11, 2020 at 7:16 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.