【问题标题】:mousemove -> draw, what's the right way?mousemove -> draw,正确的方法是什么?
【发布时间】:2016-07-21 05:03:08
【问题描述】:

我的实际用例是绘制一些东西(不是 html,而是在画布上渲染)以响应 mousemove 事件——这实际上归结为没有什么重要的事情要做,除非鼠标改变位置。

我看到 requestAnimationFrame 可以被认为是一种限制用户输入(例如 mousemove)的方法,我理解为什么它应该是这种方式以及为什么以这种方式使用它是一种代码味道如果 mousemove -> draw 不是代码的实际目的。

从 mousemove 处理程序中调用 requestAnimationFrame 有什么问题吗?

如果我不从 mousemove 处理程序调用 requestAnimationFrame 并且绘制速率实际上比用户输入循环慢(首选速率或它的工作原理),在这种情况下我是否仍能获得所需的节流?

【问题讨论】:

  • 网上已经有很多例子了。您应该包含一些代码来向我们展示您的尝试。
  • "从 mousemove 处理程序中调用 requestAnimationFrame 有什么问题吗?" 是的!所有requestAnimationFrame 调用都将被堆叠并在下次屏幕刷新时执行(通常低于mousemove 的速率)。您需要使用将在 rAF 中关闭的布尔标志,但如果不需要,请不要在同一帧中调用多个 rAF。
  • @Kaiido 非常感谢,看来我不会走那条路了。
  • @PHPglue 我确实可以访问谷歌。如果我找到了有用的答案,我就不会问了。目标是在浪费时间编写大量不起作用的代码之前研究问题。

标签: javascript mousemove requestanimationframe


【解决方案1】:

首先,this question 提供的信息非常丰富。

其次,考虑到 mousemove 事件可能比 rAF 触发更频繁,从 mousemove 事件调用 rAF 似乎是个坏主意,尽管事实上可以按照上述问题中的建议对其进行限制。

为了响应鼠标移动而进行渲染,似乎更好的方法是让 mousemove 以它想要的方式触发,并且不要尝试从那里调用 rAF。如果 mousemove 事件试图按照上述问题中的建议以荒谬的 1000Hz 触发,则处理程序唯一需要做的就是更新几个共享鼠标位置变量并在 mouseX 或 mouseY 发生变化时设置共享标志。

同样,设置一个标准的 rAF 循环并让它以它的首选速率运行,而从 rAF 回调中,检查标志以查看鼠标是否已移动,如果已移动,则将有一些东西要渲染,如果没有,然后什么都不做。

这样两个进程就不会试图相互控制,代码更简洁,更有意义。

【讨论】:

    【解决方案2】:

    这将向您展示mousemove 和动画的区别:

    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);
    

    它还在mousedown 上以'mousemove' 标题触发,但除此之外,它还会记录时间,您可以查看以确定您需要了解的内容。虽然这段代码没有演示,但您可以使用requestAnimationFrame 来暂停代码的执行,直到动画完成后再做其他事情。

    【讨论】:

    • 问题和问题在于,如果绘图过程比用户事件循环慢,鼠标事件会发生什么,以及如何处理它。 mousemove 是否只是排队并继续将所有内容拖到爬行中? Kaiido 的建议是,使用 requestanimationframe 至少提供最近的鼠标位置,如果队列中有绘图事件,则不从 mousemove 事件进行绘图。
    • 无需处理。事情会按照编写代码的顺序尽快发生。
    • 这个答案没用,没有提到 rAF,也没有解决原来的问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-12-01
    • 2015-06-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多