1

My actual use case is to draw something (not html, but render on the canvas) in response to mousemove events - it all actually boils down to nothing important to do unless the mouse changes positions.

I am seeing that requestAnimationFrame can be thought of as a way to throttle user input such as mousemove and I understand why it should be that way and why it is a code smell to use it that way if mousemove -> draw is not the actual purpose of the code.

Is there anything necessarily wrong with calling requestAnimationFrame from within the mousemove handler?

If I do not call requestAnimationFrame from the mousemove handler and the drawing rate is actually slower than the user input loop (the preferred rate or however it works), do I still get the desired throttling in that case?

Nolo
  • 846
  • 9
  • 19
  • 1
    There are plenty of examples online already. You should include some code to show us what you've tried. – StackSlave Jul 21 '16 at 05:08
  • 1
    "*Is there anything necessarily wrong with calling requestAnimationFrame from within the mousemove handler?*" yes there is ! All `requestAnimationFrame` calls will be stacked and executed at next screen refresh (which is usually at lower rate than mousemove). You need to use a boolean flag that will be turned off in the rAF, but don't call multiple rAF in the same frame if not needed. – Kaiido Jul 21 '16 at 05:10
  • @Kaiido Much appreciated, looks like I won't be going that route. – Nolo Jul 21 '16 at 05:16
  • @PHPglue I do have access to google. If I had found a useful answer I would not have asked. The goal is to research the problem before wasting time writing lots of code that doesn't work. – Nolo Jul 21 '16 at 05:17

2 Answers2

2

Firstly, the information provided in this question was very informative.

Second, given that mousemove events can possibly fire much more often than rAF, it would seem that calling rAF from the mousemove event is a bad idea, despite the fact that it can be throttled as suggested in the above question.

For the purpose of rendering in response to mouse movement, it seems that a better approach is to let mousemove fire the way it wants to and DO NOT try to call rAF from there. If the mousemove event is trying to fire at a ridiculous 1000Hz as suggested in the above question, the only thing the handler needs to do is update a couple of shared mouse position variables and set a shared flag if either mouseX or mouseY have changed.

Likewise, set up a standard rAF loop and let it run at it's preferred rate, while from the rAF callback, check the flag to see if the mouse has moved, if it has then there will be something to render, if not, then do nothing.

This way the two processes are not trying to control each other and the code is cleaner and makes more sense.

Community
  • 1
  • 1
Nolo
  • 846
  • 9
  • 19
-1

This will show you the difference of mousemove and an animation:

var doc = document, c = doc.getElementById('canvasId'), d = c.getContext('2d'), b = c.getBoundingClientRect();
function logTime(title){
  var dt = new Date;
  console.log(title+': '+dt.toLocaleDateString()+' '+dt.toTimeString().replace(/\s.*/, '')+'.'+dt.getMilliseconds());
}
function draw(e){
  logTime('mousemove');
  requestAnimationFrame(function(){
    logTime('requestAnimationFrame');
  });
  var x = e.clientX - b.left, y = e.clientY - b.top;
  d.fillRect(x, y, 1, 1);
}
c.addEventListener('mousedown', function(e){
  draw(e); c.addEventListener('mousemove', draw);
});
function stop(){
  c.removeEventListener('mousemove', draw);
}
doc.addEventListener('mouseup', stop);

It's also firing with a 'mousemove' title on mousedown, but other than that it logs times you can look at to determine what you need to know. Although this code does not demonstrate it you can use requestAnimationFrame to hold out on the execution of code until the animation is complete to do something else.

StackSlave
  • 10,613
  • 2
  • 18
  • 35
  • 1
    The problem, and the question, is about what happens to mouse events if the drawing process is _slower_ than the user event loop and how to deal with that. Do mousemove simply get queued and proceed to drag everything to a crawl? Kaiido's suggestion, using requestanimationframe at least provides the most recent mouse position, by not drawing from the mousemove event if a draw event is in the queue. – Nolo Jul 21 '16 at 06:15
  • No need to deal with it. Things will happen as fast as possible in the order the code was written. – StackSlave Jul 21 '16 at 06:43
  • This answer is useless, makes no mention of rAF and does not address the original question. – Nolo Jul 21 '16 at 19:06