如何在没有事件的情况下获得鼠标位置(不移动鼠标)?

Nor*_*mas 263 javascript mouseevent dom-events

是否可以在页面加载后使用JavaScript获取鼠标位置而无需任何鼠标移动事件(不移动鼠标)?

Tim*_*own 319

真实答案:不,这是不可能的.

好的,我刚想到了一个方法.使用覆盖整个文档的div覆盖页面.在其中,创建(比方说)2,000 x 2,000个<a>元素(以便:hover伪类可以在IE 6中工作,请参阅),每个像素大小为1个像素.:hover为那些<a>改变属性的元素创建一个CSS 规则(比方说font-family).在你的加载处理程序中,循环遍历400万个<a>元素中的每一个,检查currentStyle/ getComputedStyle()直到找到具有悬停字体的元素.从该元素推断回来以获得文档中的坐标.

NB 不要这样做.

  • 哈哈 - 在某些时候你应该谷歌周围,看看你是否可以弄清楚有多少人实际实现了这一点 (89认同)
  • http://stackoverflow.com/a/8543879/27024说,直到鼠标第一次移动时,悬停才会触发.这制定了这个计划. (27认同)
  • 也许这可以通过二分搜索实用?循环制作一对覆盖给定矩形的`<a>元素(使用绝对定位的大小`<img>`元素,我想),每次都缩小矩形.是的,这很荒谬,但是在第一次移动鼠标之前无法得到这些信息. (21认同)
  • 实际上,它是可实现的,没有太多的CPU负载(我想.我还没有测试它).在dom准备好使用javascript构建<a>元素,获取鼠标位置,然后删除所有<a>元素.在mousemouse上你应该有其他功能来取得鼠标位置.无论如何,这很有趣. (6认同)
  • @DariusBacon:这个链接的答案似乎不正确:http://jsbin.com/utocax/3.所以,是的,这种方法在某些情况下可能是实用的. (4认同)
  • @TimDown我希望看到4 mil <a>元素,而jsbin示例页面正在加载:D (3认同)
  • 您可以通过使用分而治之,例如二进制搜索来更有效地实现这一点.那你只需要两个<a>元素. (2认同)
  • 我想我可以等到鼠标移动一次而不是让CPU着火. (2认同)
  • 虽然这个有趣的解决方案听起来像是荒谬但有效的东西,但它实际上并不是一个有效的解决方案.它有与第一个问题相同的问题:当鼠标不移动时不会发生悬停事件.您可以在所有"hoverable"元素中覆盖您的页面,并且在鼠标移动之前,它们仍然不会在页面刷新时悬停.但是你可以简单地回应mousemove事件. (2认同)
  • @timetowonder:我不确定在所有浏览器和操作系统中总是如此.我很确定我有一个简单的例子,一次至少在一个浏览器中工作. (2认同)
  • @ polkovnikov.ph当我写这篇文章时,没有真正的答案,如果"真正的答案"有效,那么浏览器的行为从那时起就发生了变化.但是,我确实同意这不应该是公认的答案. (2认同)

Sup*_*ova 113

您还可以挂钩mouseenter(当页面重新加载时,当鼠标光标在页面内时触发此事件).扩展Corrupted的代码应该可以解决问题:

var x = null;
var y = null;
    
document.addEventListener('mousemove', onMouseUpdate, false);
document.addEventListener('mouseenter', onMouseUpdate, false);
    
function onMouseUpdate(e) {
  x = e.pageX;
  y = e.pageY;
  console.log(x, y);
}

function getMouseX() {
  return x;
}

function getMouseY() {
  return y;
}
Run Code Online (Sandbox Code Playgroud)

您还可以在mouseleave-event上将x和y设置为null.因此,您可以使用光标检查用户是否在您的页面上.

  • 这似乎是这里唯一真正有用的答案,这似乎很奇怪.确实(在最新的Firefox,Chrome和IE11中),mouseenter会在页面加载时触发并提供正确的坐标.这个领域的浏览器行为在过去几年中是否只是改变了? (11认同)
  • 事实上,"mouseenter"似乎没有增加任何价值.我在Chrome和IE中使用以下jsfiddle进行测试,直到你将鼠标放在内部文档(结果面板)上它们才显示cordinates:http://jsfiddle.net/xkpd784o/1/ (3认同)
  • chrome 68,使用上面的jsfiddel,即使鼠标在页面加载完成之前移动到渲染区域,也会在第一次鼠标移动时发生警报,​​而不是在加载时发生警报. (2认同)

小智 80

你可以做的是为光标xy坐标创建变量,每当鼠标移动时更新它们,并在一个间隔内调用一个函数来完成你所需要的存储位置.

当然,其缺点是需要至少一次鼠标初始移动才能使其工作.只要光标至少更新其位置一次,我们就能找到它的位置,无论它是否再次移动.

var cursorX;
var cursorY;
document.onmousemove = function(e){
    cursorX = e.pageX;
    cursorY = e.pageY;
}
setInterval(checkCursor, 1000);
function checkCursor(){
    alert("Cursor at: " + cursorX + ", " + cursorY);
}
Run Code Online (Sandbox Code Playgroud)

上述代码每秒更新一次,并显示光标所在的消息.我希望这有帮助.

  • @jake尽管OP特别要求采用非事件方法,但这个答案有益于其他来到这里寻找答案的人,也可能是一种解决方法.另外,我认为这个答案部分属于主题,因为据我所知,这是在任何给定时间获取光标位置而不必直接使用事件的最佳方法.也就是说,答案本来可以更多地说明事实,并提供一种方法来避免评论中的挑剔. (49认同)
  • 你读过这篇文章的主题了吗?OP询问如何在不使用事件的情况下获取鼠标坐标.然而你的帖子建议使用onmousemove事件. (17认同)
  • @Pichan它对我没有好处,因为我一直在寻找一种在任何事件发生之前填充那些`cursorX/Y`变量的方法. (2认同)

Ale*_*xTR 10

您可以尝试类似于Tim Down建议的内容 - 但不是为屏幕上的每个像素添加元素,而是创建2-4个元素(框),并动态更改其位置,宽度,高度以在屏幕上划分可能的位置递归地通过2-4,从而快速找到鼠标的真实位置.

例如 - 第一个元素占据屏幕的右半部分和左半部分,然后是上半部分和下半部分.到目前为止,我们已经知道鼠标位于哪个屏幕,能够重复 - 发现这个空间的哪个季度...


Sal*_*bas 9

这是我的解决方案。它导出window.currentMouseXwindow.currentMouseY属性,您可以在任何地方使用。它最初使用悬停元素(如果有)的位置,然后监听鼠标移动以设置正确的值。

(function () {
    window.currentMouseX = 0;
    window.currentMouseY = 0;

    // Guess the initial mouse position approximately if possible:
    var hoveredElement = document.querySelectorAll(':hover');
    hoveredElement = hoveredElement[hoveredElement.length - 1]; // Get the most specific hovered element

    if (hoveredElement != null) {
        var rect = hoveredElement.getBoundingClientRect();
        // Set the values from hovered element's position
        window.currentMouseX = window.scrollX + rect.x;
        window.currentMouseY = window.scrollY + rect.y;
    }

    // Listen for mouse movements to set the correct values
    window.addEventListener('mousemove', function (e) {
        window.currentMouseX = e.pageX;
        window.currentMouseY = e.pageY;
    }, /*useCapture=*/true);
}())
Run Code Online (Sandbox Code Playgroud)

Composr CMS来源: https://github.com/ocproducts/composr/commit/a851c19f925be20bc16bfe016be42924989f262e#diff-b162dc9c35a97618a96748639ff41251R1202


Ale*_*son 8

如果渲染2,000 x 2,000个<a>元素,则@Tim Down的答案无效。

好的,我刚刚想到了一种方法。用覆盖整个文档的div覆盖页面。在其中,创建(说)2,000 x 2,000个元素(以便:hover伪类可在IE 6中使用,请参见),每个元素的大小为1像素。为那些更改属性的元素创建CSS:hover规则(比如说font-family)。在负载处理程序中,循环浏览这400万个元素中的每个元素,检查currentStyle / getComputedStyle()直到找到带有悬停字体的元素。从此元素外推,以获取文档中的坐标。

注意:请勿这样做。

但是您不必一次渲染400万个元素,而是使用二进制搜索。只需使用4个<a>元素即可:

  • 步骤1:将整个屏幕视为开始搜索区域
  • 步骤2:将搜寻区域分割成2 x 2 = 4个矩形 <a>元素
  • 步骤3:使用该getComputedStyle()函数确定将鼠标悬停在哪个矩形中
  • 步骤4:将搜索区域缩小到该矩形,然后从步骤2开始重复。

这样,考虑到屏幕的宽度不超过2048像素,您最多需要重复这些步骤11次。

因此,您将生成最多11 x 4 = 44个<a>元素。

如果您不需要确定鼠标的位置精确到一个像素,而是说10px精度就可以了。您最多将重复步骤8次,因此您需要绘制最多8 x 4 = 32个<a>元素。

<a>由于DOM通常很慢,因此生成和销毁元素的效果也不佳。相反,你可以只重用最初4个<a>元素,只是调整自己topleftwidthheight通过步骤你循环。

现在,创建4 <a>也是一个过大的杀伤力。相反,在每个矩形中<a>进行测试时,可以重复使用相同的一个元素getComputedStyle()。因此,与其将搜索区域划分为2 x 2个<a>元素,不如<a>通过使用topleft样式属性移动元素来重用单个元素。

因此,您只需要单个<a>元素更改其widthheight最大11次,然后更改其topleft最大44次,您将拥有准确的鼠标位置。


Ste*_*rya 6

最简单的解决方案,但不是 100% 准确

$(':hover').last().offset()
Run Code Online (Sandbox Code Playgroud)

结果:{top: 148, left: 62.5}
结果取决于最接近的元素大小,并undefined在用户切换选项卡时返回


Mak*_*kan 5

是的,这是可能的。

如果您向文档添加“mouseover”事件,它将立即触发,并且您可以获得鼠标位置,当然,如果鼠标指针位于文档上方。

   document.addEventListener('mouseover', setInitialMousePos, false);

   function setInitialMousePos( event ) {
       console.log( event.clientX, event.clientY);
       document.removeEventListener('mouseover', setInitialMousePos, false);
   }
Run Code Online (Sandbox Code Playgroud)

以前可以读取鼠标位置,window.event但现在已弃用。

  • 这不再起作用了。使用 Chrome 107 进行测试。 (3认同)