331

页面加载后是否可以在没有任何鼠标移动事件(不移动鼠标)的情况下使用 JavaScript 获取鼠标位置?

4

15 回答 15

378

真正的答案:不,这是不可能的。

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

注意不要这样做

于 2010-04-08T15:20:27.143 回答
132

编辑 2020:不再起作用。似乎是这样,浏览器供应商修补了这一点。因为大多数浏览器都依赖于 Chromium,所以它可能是它的核心。

旧答案:您也可以挂钩 mouseenter (此事件在页面重新加载后触发,当鼠标光标在页面内时)。扩展损坏的代码应该可以解决问题:

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

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

于 2014-04-10T11:33:31.457 回答
88

您可以做的是为光标的坐标创建变量,xy鼠标移动时更新它们,并在间隔上调用一个函数来对存储的位置执行您需要的操作。

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

var cursor_x = -1;
var cursor_y = -1;
document.onmousemove = function(event)
{
 cursor_x = event.pageX;
 cursor_y = event.pageY;
}
setInterval(check_cursor, 1000);
function check_cursor(){console.log('Cursor at: '+cursor_x+', '+cursor_y);}

前面的代码每秒更新一次,并显示光标所在位置的消息。我希望这有帮助。

于 2012-01-24T19:49:16.483 回答
13

<a>如果您渲染 2,000 x 2,000 个元素,@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 步开始重复。

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

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

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

<a>由于 DOM 通常很慢,因此生成然后销毁元素也不会执行。相反,您可以重复使用最初的 4 个<a>元素,并在循环执行步骤时调整它们的、top和。leftwidthheight

现在,创建 4<a>也是一种矫枉过正。相反,您可以在每个矩形中<a>进行测试时重复使用相同的一个元素。getComputedStyle()因此,不要将搜索区域拆分为 2 x 2元素,只需通过使用和样式属性移动它来<a>重用单个元素。<a>topleft

因此,您只需将单个<a>元素更改其widthheight最大值 11 次,并将其topleft最大值更改 44 次,您将获得准确的鼠标位置。

于 2017-04-10T14:48:47.163 回答
10

您可以尝试类似于 Tim Down 建议的方法 - 但不要在屏幕上为每个像素创建元素,而是仅创建 2-4 个元素(框),并动态更改它们的位置、宽度、高度以划分屏幕上可能的位置通过 2-4 递归,从而快速找到鼠标的实际位置。

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

于 2015-02-11T08:46:17.627 回答
7

这是我的解决方案。它导出可以在任何地方使用的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);
}())

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

于 2018-09-02T21:08:56.560 回答
5

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

$(':hover').last().offset()

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

于 2018-01-10T12:08:04.377 回答
2

是的,这是可能的。

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

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

   function setInitialMousePos( event ) {
       console.log( event.clientX, event.clientY);
       document.removeEventListener('mouseover', setInitialMousePos, false);
   }

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

于 2021-08-27T01:01:05.677 回答
1
var x = 0;
var y = 0;

document.addEventListener('mousemove', onMouseMove, false)

function onMouseMove(e){
    x = e.clientX;
    y = e.clientY;
}

function getMouseX() {
    return x;
}

function getMouseY() {
    return y;
}
于 2012-11-09T14:31:57.223 回答
1

我实现了一个横向/纵向的搜索,(先做一个横向排列的全垂直线链接的div,然后再做一个纵向排列的全横向线链接的div,简单看看哪个有hover状态)就像上面Tim Down的想法,和它工作得非常快。可悲的是,在 KDE 上的 Chrome 32 上不起作用。

jsfiddle.net/5XzeE/4/

于 2013-11-06T01:36:46.327 回答
1

您不必移动鼠标来获取光标的位置。除了mousemove之外的事件也会报告该位置。这里以点击事件为例:

document.body.addEventListener('click',function(e)
{
    console.log("cursor-location: " + e.clientX + ',' + e.clientY);
});
于 2017-06-28T17:23:27.363 回答
1

在@SuperNova的回答中,这是一种使用 ES6 类的方法,可以this在回调中保持上下文正确:

class Mouse {
  constructor() {
    this.x = 0;
    this.y = 0;
    this.callbacks = {
      mouseenter: [],
      mousemove: [],
    };
  }

  get xPos() {
    return this.x;
  }

  get yPos() {
    return this.y;
  }

  get position() {
    return `${this.x},${this.y}`;
  }

  addListener(type, callback) {
    document.addEventListener(type, this); // Pass `this` as the second arg to keep the context correct
    this.callbacks[type].push(callback);
  }

  // `handleEvent` is part of the browser's `EventListener` API.
  // https://developer.mozilla.org/en-US/docs/Web/API/EventListener/handleEvent
  handleEvent(event) {
    const isMousemove = event.type === 'mousemove';
    const isMouseenter = event.type === 'mouseenter';

    if (isMousemove || isMouseenter) {
      this.x = event.pageX;
      this.y = event.pageY;
    }

    this.callbacks[event.type].forEach((callback) => {
      callback();
    });
  }
}

const mouse = new Mouse();

mouse.addListener('mouseenter', () => console.log('mouseenter', mouse.position));
mouse.addListener('mousemove', () => console.log('mousemove A', mouse.position));
mouse.addListener('mousemove', () => console.log('mousemove B', mouse.position));

于 2018-02-02T06:16:00.117 回答
1

不是鼠标位置,但是,如果您正在寻找当前光标位置(用于获取最后输入的字符等用例),那么下面的代码片段可以正常工作。
这将为您提供与文本内容相关的光标索引。

window.getSelection().getRangeAt(0).startOffset
于 2020-12-11T13:05:19.890 回答
0

我设想也许您有一个带有计时器的父页面,并且在一定时间或任务完成后,您将用户转发到新页面。现在您需要光标位置,因为它们正在等待,它们不一定会触摸鼠标。因此,使用标准事件在父页面上跟踪鼠标,并在 get 或 post 变量中将最后一个值传递给新页面。

您可以在父页面上使用 JHarding 的代码,以便在全局变量中始终提供最新位置:

var cursorX;
var cursorY;
document.onmousemove = function(e){
    cursorX = e.pageX;
    cursorY = e.pageY;
}

这不会帮助通过您的父页面以外的方式导航到此页面的用户。

于 2013-10-17T19:59:38.790 回答
-1

我想我可能有一个合理的解决方案,不计算 div 和像素..lol

只需使用动画帧或函数的时间间隔。您仍然需要一次鼠标事件,尽管只是为了启动,但从技术上讲,您可以将其放置在您喜欢的任何位置。

本质上,我们一直在跟踪一个虚拟 div,而无需鼠标移动。

// create a div(#mydiv) 1px by 1px set opacity to 0 & position:absolute;

下面是逻辑。。

var x,y;


$('body').mousemove(function( e ) {

    var x = e.clientX - (window.innerWidth / 2);
    var y = e.clientY - (window.innerHeight / 2);
 }


function looping (){

   /* track my div position 60 x 60 seconds!
      with out the mouse after initiation you can still track the dummy div.x & y
      mouse doesn't need to move.*/

   $('#mydiv').x = x;    // css transform x and y to follow 
   $('#mydiv)'.y = y;

   console.log(#mydiv.x etc)

   requestAnimationFrame( looping , frame speed here);
}  
于 2019-01-18T12:56:33.340 回答