【问题标题】:Tracking relative mouse position without a mousemove event在没有 mousemove 事件的情况下跟踪相对鼠标位置
【发布时间】:2014-09-24 00:22:44
【问题描述】:

我需要在我的应用程序中跟踪鼠标相对于 <canvas> 元素的位置。目前,我有一个mousemove 事件侦听器附加到<canvas>,它在触发时更新我的​​鼠标位置,使用offsetX/offsetY(如果可用)或layerX/layerY(当offsetX/Y 是无法使用。使用offsetX/YlayerX/Y 为我提供了相对于<canvas> 的鼠标坐标,这正是我想要的。当我的应用程序发挥它的魔力时,各种 CSS 3d 变换被应用到 <canvas>,即使 <canvas> 非常变换,offsetX/Y 仍然在 <canvas> 的本地变换坐标空间内为我提供准确的坐标.

这有点令人困惑,所以我将尝试举例说明。如果我的<canvas> 的宽度和高度均为 100px,并且相对于浏览器视口位于 (0,0),并且我单击 (50,50)(在视口坐标中),则对应于 (50,50 ) 在我的<canvas> 中,50 是通过offsetXoffsetY(正确)返回的值。如果我然后将transform: translate3d(20px,20px,0px) 应用到我的<canvas> 并单击(50,50)(在视口坐标中),因为我的画布已经向下移动了 20px 和向右移动了 20px,这实际上对应于 (30,30) 相对到<canvas>,30 是(正确)通过offsetXoffsetY 返回的值。

我面临的问题是当用户没有实际移动鼠标时该怎么办,但 <canvas> 正在被转换。我只是在mousemove事件上更新鼠标位置,没有mousemove时怎么办?

例如。我的鼠标位于 (50,50),并且没有对 <canvas> 应用任何转换。我的this.mouseXthis.mouseY 都等于50;当我将鼠标移动到 (50,50) 时,它们被保存在最后的 mousemove 事件中。完全不移动鼠标,我将上述转换 (transform: translate3d(20px,20px,0px)) 应用到我的<canvas>。现在,我需要this.mouseXthis.mouseY 都等于30,因为这是我的鼠标相对于<canvas> 的当前变换的新位置。但是this.mouseXthis.mouseY 仍然等于50。由于我从未移动鼠标,因此没有触发mousemove 事件,并且那些保存的坐标从未更新。

我该如何处理?我考虑过创建一个新的 jQuery 事件,根据我的旧/以前的鼠标位置手动分配一些属性(pageXpageY?),然后触发该事件,但我认为这不会导致浏览器重新计算 offsetXoffsetY 属性。我也一直在考虑采用已知的旧/以前的鼠标位置并将其乘以我的转换矩阵,但这将变得非常复杂,因为我的鼠标坐标位于二维空间中,但我正在应用的转换@987654364 @ 都是 3d 变换。

我想真的,我想要做的是获取我已知的 2d 页面位置并将其投射到 3d 空间中,并找出我在哪里点击转换后的<canvas>,所有这些都在 javascript 中(jQuery 可用)。

这可能吗?这有意义吗?

【问题讨论】:

  • 如果您想在不移动鼠标的情况下获得“新”鼠标坐标 - 那么我认为您必须获取“旧”坐标(来自最后一个 mousemove 事件),然后“应用”自己转换到这些值以计算正确的“新”坐标应该是什么。
  • @CBroe 我真的希望避免这种情况,但你可能是对的......

标签: javascript css events css-transforms


【解决方案1】:

适用于所有浏览器

 var mouseX=0;
 var mouseY=0;
 var canvas = document.querySelector('#canvas');
 var rect = canvas.getBoundingClientRect();
 document.onmousemove = function(e) {
      mouseX=e.clientX-rect.left;
      mouseY=e.clientY-rect.top;
};
function updateCoords() {
      mouseX=e.clientX-mouseX;
      mouseY=e.clientY-mouseY;
      setTimeout(updatecoords,10);
}

现在我们可以调用一次updateCoords()函数来重复检查新的位置。

 updateCoords();

您可以在 updateCoords() 函数中添加代码,它将每 10 毫秒执行一次

概念:mouseXmouseY 变量在 mousemove 事件时更新,并且在画布位置发生任何变化时也会更新。

【讨论】:

    【解决方案2】:

    看起来您想刷新鼠标位置值,即使您不移动鼠标也是如此。你应该尝试这样的事情:

    var event = '';
    var counter = 1;
    
    $(function(e){
        event = e;
        window.setInterval(refresh, 10);
    });
    
    $(document).mousemove(function(e){
        event = e;
        refresh;
    });
    
    function refresh(){
        counter++;
        $('#mousepos').val("event.pageX: " + event.pageX + ", event.pageY: " + event.pageY + ", counter: " + counter)
    }
    

    计数器仅用于刷新的可视化。您可以将间隔设置为您想要的所有内容(10 = 10ms = 0.01s)只需将所有内容从 .mousemove() 事件移动到此 refresh() 函数中并正确调用它,即使您不移动鼠标位置也应该更新你的鼠标。

    看看这个小提琴的生活例子:http://jsfiddle.net/82cmxw8L/1

    编辑:

    因为我的小提琴对提问者不起作用,所以我更新了它:http://jsfiddle.net/82cmxw8L/8/

    新的是,鼠标位置现在每 0.1 秒设置一次,无论如何,而不是仅在鼠标移动时更新。

    【讨论】:

    • 感谢您的建议,但不幸的是,这看起来不太适合我的目的。我编辑了你的 jsfiddle 来测试一下。我添加了一个框,当您将鼠标悬停在它上面时它会向右滑动,并将事件附加到该框而不是文档,当您将鼠标悬停在框上并滑动时,您可以看到 offsetX 和 offsetY 值(鼠标位置相对于 div 而不是页面)在您实际移动鼠标之前不会被更新。
    • 我更新了我的答案。它现在应该可以按预期工作了。
    猜你喜欢
    • 1970-01-01
    • 2017-12-25
    • 2011-02-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-06
    • 2012-12-30
    相关资源
    最近更新 更多