16

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

Robbie Wxyz
  • 7,671
  • 2
  • 32
  • 47
Hannington Mambo
  • 998
  • 2
  • 13
  • 28
  • 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 interruptable – mplungjan Jul 15 '13 at 04:39
  • 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 function – Seth McClaine Jul 15 '13 at 04:40
  • use setTimeout instead – Loïc Faure-Lacroix Jul 15 '13 at 04:45
  • Thanks, mplungjan, for the insight. I can rework this part. – Hannington Mambo Jul 15 '13 at 04:48
  • Loic, that could just do it. Thanks. – Hannington Mambo Jul 15 '13 at 04:50
  • 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? – Hannington Mambo Jul 15 '13 at 04:53
  • 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. – Hannington Mambo Jul 16 '13 at 03:22
  • @HanningtonMambo: Were you able to figure this out? If so, can you mark this post as answered (click the green check). – Robbie Wxyz Jan 23 '15 at 23:49

2 Answers2

26

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.

Robbie Wxyz
  • 7,671
  • 2
  • 32
  • 47
-1

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

Stephen.W
  • 1,649
  • 13
  • 14