Javascript 如何在没有事件的情况下获取鼠标位置(不移动鼠标)?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2601097/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to get the mouse position without events (without moving the mouse)?
提问by Norbert Tamas
Is it possible to get the mouse position with JavaScript after page loads without any mouse movement event (without moving the mouse)?
在没有任何鼠标移动事件(不移动鼠标)的情况下,是否可以在页面加载后使用 JavaScript 获取鼠标位置?
回答by Tim Down
Real answer: No, it's not possible.
真正的答案:不,这是不可能的。
OK, I have just thought of a way. Overlay your page with a div that covers the whole document. Inside that, create (say) 2,000 x 2,000 <a>elements (so that the :hoverpseudo-class will work in IE 6, see), each 1 pixel in size. Create a CSS :hoverrule for those <a>elements that changes a property (let's say font-family). In your load handler, cycle through each of the 4 million <a>elements, checking currentStyle/ getComputedStyle()until you find the one with the hover font. Extrapolate back from this element to get the co-ordinates within the document.
好的,我刚刚想到了一个方法。用覆盖整个文档的 div 覆盖您的页面。在里面,创建(比如)2,000 x 2,000 个<a>元素(这样:hover伪类可以在 IE 6 中工作,见),每个 1 像素大小。:hover为那些<a>改变属性的元素创建一个 CSS规则(比方说font-family)。在您的负载处理程序中,循环遍历 400 万个<a>元素中的每一个,检查currentStyle/getComputedStyle()直到找到带有悬停字体的那个。从此元素推断回来以获取文档中的坐标。
N.B. DON'T DO THIS.
注意不要这样做。
回答by SuperNova
Edit 2020: This does notwork any more.It seems so, that the browser vendors patched this out. Because the most browsers rely on chromium, it might be in its core.
2020 年编辑:这不再起作用。似乎是这样,浏览器供应商对此进行了修补。因为大多数浏览器都依赖于铬,所以它可能是其核心。
Old answer: You can also hook mouseenter (this event is fired after page reload, when the mousecursor is inside the page). Extending Corrupted's code should do the trick:
旧答案:您还可以挂钩 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;
}
You can also set x and y to null on mouseleave-event. So you can check if the user is on your page with it's cursor.
您还可以在 mouseleave-event 上将 x 和 y 设置为 null。因此,您可以使用光标检查用户是否在您的页面上。
回答by JHarding
What you can do is create variables for the xand ycoordinates of your cursor, update them whenever the mouse moves and call a function on an interval to do what you need with the stored position.
您可以做的是为光标的坐标x和y坐标创建变量,在鼠标移动时更新它们,并在一个时间间隔内调用一个函数来对存储的位置执行您需要的操作。
The downside to this of course is that at least one initial movement of the mouse is required to have it work. As long as the cursor updates its position at least once, we are able to find its position regardless of whether it moves again.
当然,这样做的缺点是至少需要鼠标的一次初始移动才能使其工作。只要光标至少更新一次位置,无论它是否再次移动,我们都可以找到它的位置。
var cursorX;
var cursorY;
document.onmousemove = function(e){
cursorX = e.pageX;
cursorY = e.pageY;
}
setInterval(checkCursor, 1000);
function checkCursor(){
alert("Cursor at: " + cursorX + ", " + cursorY);
}
The preceding code updates once a second with a message of where your cursor is. I hope this helps.
前面的代码每秒更新一次,并显示光标所在位置的消息。我希望这有帮助。
回答by AlexTR
You could try something similar to what Tim Down suggested - but instead of having elements for each pixel on the screen, create just 2-4 elements (boxes), and change their location, width, height dynamically to divide the yet possible locations on screen by 2-4 recursively, thus finding the mouse real location quickly.
您可以尝试类似于 Tim Down 建议的方法 - 但不要为屏幕上的每个像素创建元素,只需创建 2-4 个元素(框),并动态更改它们的位置、宽度、高度以划分屏幕上可能的位置通过2-4递归,从而快速找到鼠标的真实位置。
For example - first elements take right and left half of screen, afterwards the upper and lower half. By now we already know in which quarter of screen the mouse is located, are able to repeat - discover which quarter of this space...
例如 - 第一个元素占据屏幕的左右半部分,然后是上半部分和下半部分。现在我们已经知道鼠标位于屏幕的哪四分之一,可以重复 - 发现这个空间的哪四分之一......
回答by Alex Peterson
@Tim Down's answer is not performant if you render 2,000 x 2,000 <a>elements:
如果您渲染 2,000 x 2,000 个<a>元素,@Tim Down 的答案就不是很有效:
OK, I have just thought of a way. Overlay your page with a div that covers the whole document. Inside that, create (say) 2,000 x 2,000 elements (so that the :hover pseudo-class will work in IE 6, see), each 1 pixel in size. Create a CSS :hover rule for those elements that changes a property (let's say font-family). In your load handler, cycle through each of the 4 million elements, checking currentStyle / getComputedStyle() until you find the one with the hover font. Extrapolate back from this element to get the co-ordinates within the document.
N.B. DON'T DO THIS.
好的,我刚刚想到了一个方法。用覆盖整个文档的 div 覆盖您的页面。在里面,创建(比如)2,000 x 2,000 个元素(这样 :hover 伪类将在 IE 6 中工作,请参阅),每个 1 像素大小。为那些改变属性的元素创建一个 CSS :hover 规则(比如 font-family)。在您的负载处理程序中,循环遍历 400 万个元素中的每一个,检查 currentStyle / getComputedStyle() 直到找到带有悬停字体的那个。从此元素推断回来以获取文档中的坐标。
注意不要这样做。
But you don't have to render 4 million elements at once, instead use binary search. Just use 4 <a>elements instead:
但是您不必一次渲染 400 万个元素,而是使用二分搜索。只需使用 4 个<a>元素:
- Step 1: Consider the whole screen as the starting search area
- Step 2: Split the search area into 2 x 2 = 4 rectangle
<a>elements - Step 3: Using the
getComputedStyle()function determine in which rectangle mouse hovers - Step 4: Reduce the search area to that rectangle and repeat from step 2.
- 第 1 步:将整个屏幕视为起始搜索区域
- 第 2 步:将搜索区域拆分为 2 x 2 = 4 个矩形
<a>元素 - 步骤 3:使用
getComputedStyle()函数确定鼠标悬停在哪个矩形 - 第 4 步:将搜索区域缩小到该矩形并从第 2 步开始重复。
This way you would need to repeat these steps max 11 times, considering your screen is not wider than 2048px.
考虑到您的屏幕宽度不超过 2048 像素,这样您最多需要重复这些步骤 11 次。
So you will generate max 11 x 4 = 44 <a>elements.
因此,您将生成最多 11 x 4 = 44 个<a>元素。
If you don't need to determine the mouse position exactly to a pixel, but say 10px precision is OK. You would repeat the steps at most 8 times, so you would need to draw max 8 x 4 = 32 <a>elements.
如果您不需要精确地将鼠标位置确定为一个像素,但说 10px 精度就可以了。您最多可以重复这些步骤 8 次,因此您最多需要绘制 8 x 4 = 32 个<a>元素。
Also generating and then destroying the <a>elements is not performat as DOM is generally slow. Instead, you can just reuse the initial 4 <a>elements and just adjust their top, left, widthand heightas you loop through steps.
<a>由于 DOM 通常很慢,因此生成然后销毁元素也不会执行。相反,您可以只重用最初的 4 个<a>元素,并在循环执行步骤时调整它们的top, left,width和height。
Now, creating 4 <a>is an overkill as well. Instead, you can reuse the same one <a>element for when testing for getComputedStyle()in each rectangle. So, instead of splitting the search area into 2 x 2 <a>elements just reuse a single <a>element by moving it with topand leftstyle properties.
现在,创建 4<a>也是一种矫枉过正。相反,您可以在每个矩形中<a>进行测试时重复使用相同的一个元素getComputedStyle()。因此,不要将搜索区域拆分为 2 x 2<a>元素,只需<a>通过使用top和left样式属性移动它来重用单个元素。
So, all you need is a single <a>element change its widthand heightmax 11 times, and change its topand leftmax 44 times and you will have the exact mouse position.
所以,你需要的是一个单一的<a>元素来改变它width和height最大11倍,并改变其top和left最大44倍,你将有确切的鼠标位置。
回答by StefansArya
The most simple solution but not 100% accurate
最简单的解决方案,但不是 100% 准确
$(':hover').last().offset()
Result: {top: 148, left: 62.5}
The result depend on the nearest element size and return undefinedwhen user switched the tab
结果:{top: 148, left: 62.5}
结果取决于最近的元素大小并undefined在用户切换选项卡时返回
回答by StefansArya
I envision that maybe you have a parent page with a timer and after a certain amount of time or a task is completed, you forward the user to a new page. Now you want the cursor position, and because they are waiting, they aren't necessarily touching the mouse. So track the mouse on the parent page using standard events and pass the last value to the new page in a get or a post variable.
我设想可能你有一个带计时器的父页面,在一定时间或任务完成后,你将用户转发到一个新页面。现在您需要光标位置,并且因为它们在等待,所以它们不一定要触摸鼠标。因此,使用标准事件跟踪父页面上的鼠标,并在 get 或 post 变量中将最后一个值传递给新页面。
You can use JHarding's code on your parent page so that the latest position is always available in a global variable:
您可以在父页面上使用 JHarding 的代码,以便在全局变量中始终可用最新位置:
var cursorX;
var cursorY;
document.onmousemove = function(e){
cursorX = e.pageX;
cursorY = e.pageY;
}
This won't help users that navigate to this page by means other than your parent page.
这不会帮助通过您的父页面以外的方式导航到此页面的用户。
回答by user2958613
I implemented a horizontal/vertical search, (first make a div full of vertical line links arranged horizontally, then make a div full of horizontal line links arranged vertically, and simply see which one has the hover state) like Tim Down's idea above, and it works pretty fast. Sadly, does not work on Chrome 32 on KDE.
我实现了一个水平/垂直搜索,(首先制作一个充满水平排列的垂直线链接的 div,然后制作一个充满垂直排列的水平线链接的 div,并简单地查看哪个具有悬停状态)就像上面 Tim Down 的想法,以及它工作得非常快。遗憾的是,它不适用于 KDE 上的 Chrome 32。
jsfiddle.net/5XzeE/4/
jsfiddle.net/5XzeE/4/
回答by Lonnie Best
You do not have to movethe mouse to get the cursor's location. The location is also reported on events other than mousemove. Here's a click-eventas an example:
您不必移动鼠标即可获得光标的位置。除了mousemove之外的事件也会报告该位置。以点击事件为例:
document.body.addEventListener('click',function(e)
{
console.log("cursor-location: " + e.clientX + ',' + e.clientY);
});
回答by Patrick Berkeley
Riffing on @SuperNova's answer, here's an approach using ES6 classes that keeps the context for thiscorrect in your callback:
根据@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));

