鼠标左键向下并在 Chrome 上移动时 Html Canvas 滞后

Posted

技术标签:

【中文标题】鼠标左键向下并在 Chrome 上移动时 Html Canvas 滞后【英文标题】:Html Canvas lag when Left Mouse is down and moving on Chrome 【发布时间】:2015-12-09 10:05:51 【问题描述】:

我已经创建了一个画布,并在其中添加了鼠标事件:

canvas = document.getElementById('canvas');
context = canvas.getContext('2d');
canvas.width = screenWidth;
canvas.height = screenHeight;

... 

// CALLED AT START:
function setup() 
    // Mouse movement:
    document.onmousemove = function(e) 
        e.preventDefault();
        target.x = e.pageX;
        target.y = e.pageY;
        angle = Math.atan2((target.y - localPlayer.getY()),
            (target.x - localPlayer.getX()));
        // Distance to mouse Check:
        var dist = Math.sqrt((localPlayer.getX() - target.x)
            * (localPlayer.getX() - target.x) + (localPlayer.getY() - target.y)
            * (localPlayer.getY() - target.y));
        var speedMult = dist / (canvas.height / 4);
        socket.emit("update", 
            ...
        );
    
    document.onmousedown = function(e) 
        e.preventDefault();
    

现在的问题是,当我按住唯一的鼠标左键并同时移动鼠标时,我的游戏会滞后很多。简单地移动鼠标不会导致延迟。我已经在 chrome 和 firefox 上对此进行了测试。看来我只能在 chrome 上重新创建问题。使用鼠标中键或右键在游戏中具有相同的行为并且不会导致延迟。只有在使用鼠标左键时才会导致延迟。

我四处寻找答案,发现我应该防止像这样的默认行为:

e.preventDefault();

但这并没有解决问题。我还尝试更新屏幕上代表鼠标位置的数字。并且更新正常。只有游戏本身落后了。是不是在按住左键时永远不会调用 onMouseMoved ?但是为什么用中间和右键调用呢?

问题应该出在我在 move 方法中调用的代码上,因为当我不按住左键时它可以正常工作,并且在 firefox 上也可以正常工作。一定有其他事情发生。

编辑:我决定在 chrome 上录制,看看发生了什么。结果如下:

真正奇怪的是,当我按下鼠标中键或右键时,游戏会做同样的事情,但一点也不卡顿。你在做什么铬?

编辑:在这里进行测试:www.vertix.io 请注意,似乎并非每个人都能够重现此问题。

感谢您的宝贵时间。

【问题讨论】:

您真的每 0.033 秒分配两个新的事件处理程序吗?为什么?另外,draw() 在哪里 我会使用画布本身来代替文档... 如果你需要帮助,你需要创建一个 MCVE 首先将所有代码移出onmousemove 事件并使用window.requestAnimationFrame 更新您需要的内容。在鼠标移动事件中,只需抓取并存储鼠标坐标,它不应该是您执行应用程序逻辑的地方。还为 Chrome 添加 user-select: none; 样式规则添加“-webkit-”到正文或画布元素以停止拖动选择。我不知道这是否会解决您的问题,因为您没有提供复制问题所需的内容 可能有html解决方案:尝试添加oncontextmenu="return false;"到画布标签 【参考方案1】:

当您按住鼠标左键并同时移动它时,您就是拖动

编辑:在某些版本的 Chrome 中,有一个错误(当我发布这个答案时,我有它,现在我没有),导致 drag 事件甚至被触发没有具有draggable 属性的元素。通常,drag 事件只能从 draggable 属性设置为 true 的元素中触发(默认情况下可拖动的图像和锚点除外)。

根据MDN,当drag事件被触发时,mouse事件,例如mousemove,不是,这意味着你的函数没有被调用。

一种可能的解决方案是对dragmousemove 事件使用相同的函数:

function mouseMove(e) 
    //do your things here
    ...


document.addEventListener('mousemove', mouseMove);

document.addEventListener('drag', mouseMove);

注意:如果您对两个事件使用相同的函数,您应该知道您在函数中使用了事件的哪些属性,因为 @987654333 之间的区别@ 和 mousemove 事件。这两个事件不包含完全相同的属性,并且它们的某些属性的行为可能不同。

【讨论】:

【参考方案2】:

你考虑过节流吗?

查看https://blog.toggl.com/2013/02/increasing-perceived-performance-with-_throttle/

【讨论】:

【参考方案3】:

您在文档上有鼠标事件。由于我们看不到您在文档上的内容,因此很难知道这是否是您的问题的原因。

尝试仅将鼠标事件移动到画布上,因为我认为这是您唯一需要它的地方。如果文档不是游戏的一部分,则没有必要为文档处理事件,如果子元素附加了事件,则文档是列表中的最后一个。他们先走,然后它会冒泡到你的。

看起来您正在使用某种类型的框架,很有可能另一个鼠标事件侦听器是框架工作的一部分,它可能会因为不阻止默认设置而减慢您的速度。您必须搜索框架以查看它是否具有任何鼠标事件的侦听器。

并使用addEventListener,而不是直接通过.onmousedown = eventHandler附加事件 例如canvas.addEventListener("mousedown",eventHandler);

并将事件侦听器添加到您需要它的元素,而不是文档。

【讨论】:

【参考方案4】:
function mouseMove(e) 
//do your things here
...
 

 document.onmousemove = mouseMove;

  document.ondrag = function(e) 
mouseMove(e);
//do another things
...

【讨论】:

尝试添加一些描述。

以上是关于鼠标左键向下并在 Chrome 上移动时 Html Canvas 滞后的主要内容,如果未能解决你的问题,请参考以下文章

鼠标左键点击是啥意思?

我的鼠标左键按一下,就像是点击了两下,怎么搞的

DataGrid 用鼠标拖动改变列宽,怎么做

jq鼠标事件

JQuery 鼠标事件简介

如何同时听鼠标移动和左键