确定鼠标指针位于 JavaScript 中的哪个元素之上

我想要一个函数,告诉我哪个元素的鼠标光标结束。

因此,例如,如果用户的鼠标位于这个文本区域上(id 为 wmd-input) ,那么调用 window.which_element_is_the_mouse_on()在功能上等效于 $("#wmd-input")

143225 次浏览

您可以查看 mouseover事件的目标在某个合适的祖先上:

var currentElement = null;


document.addEventListener('mouseover', function (e) {
currentElement = e.target;
});

这是小样。

演示

有一个非常酷的函数叫 document.elementFromPoint,它的功能和听起来一样。

我们需要找到鼠标的 x 和 y 坐标,然后使用这些值调用它:

document.addEventListener('mousemove', e => {
console.clear()
console.log( document.elementFromPoint(e.clientX, e.clientY) )
}, {passive: true})
[class^='level']{
width: 100px;
height: 100px;
padding: 15px;
background: #00000033;
}
<div class='level-1'>
<div class='level-2'>
<div class='level-3'>
Hover
</div>
</div>
</div>

ElementFromPoint

JQuery 事件对象

首先我要说的是,我不推荐使用我将要建议的方法。最好使用事件驱动开发,并且只将事件绑定到您感兴趣的元素,以了解鼠标是否已经结束了 mouseovermouseoutmouseentermouseleave等等。

如果您完全能够知道哪个元素已经结束,那么您需要编写一个函数,将 mouseover事件绑定到 DOM 中的所有内容,然后将当前元素存储在某个变量中。

你可以这样做:

window.which_element_is_the_mouse_on = (function() {


var currentElement;


$("body *").on('mouseover', function(e) {
if(e.target === e.currentTarget) {
currentElement = this;
}
});


return function() {
console.log(currentElement);
}
}());

基本上,我已经创建了一个立即函数,它在所有元素上设置事件,并将当前元素存储在闭包中,以最小化您的内存占用。

下面是一个工作演示,它每秒调用 window.which_element_is_the_mouse_on,并将鼠标当前移动到控制台的元素记录到日志中。

Http://jsfiddle.net/lwfpj/1/

鼠标悬停事件会冒泡,所以你可以在主体上放一个监听器,等待它们冒泡,然后抓取 event.targetevent.srcElement:

function getTarget(event) {
var el = event.target || event.srcElement;
return el.nodeType == 1? el : el.parentNode;
}


<body onmouseover="doSomething(getTarget(event));">

在较新的浏览器中,您可以执行以下操作:

document.querySelectorAll( ":hover" );

这将为您提供一个 NodeList,其中包含鼠标当前按文档顺序移动的项目。NodeList 中的最后一个元素是最具体的,前面的每个元素都应该是父元素、祖元素等等。

<!-- One simple solution to your problem could be like this: -->


<div>
<input type="text" id="fname" onmousemove="javascript: alert(this.id);" />
<!-- OR -->
<input type="text" id="fname" onclick="javascript: alert(this.id);" />
</div>
<!-- Both mousemove over the field & click on the field displays "fname"-->
<!-- Works fantastic in IE, FireFox, Chrome, Opera. -->
<!-- I didn't test it for Safari. -->

虽然下面的内容可能并不能真正回答这个问题,因为这是谷歌的第一个结果(谷歌可能不会问完全相同的问题:) ,希望它能提供一些额外的输入。

实际上有两种不同的方法来获得鼠标当前所有元素的列表(对于较新的浏览器来说,可能是这样) :

“结构化”方法——升序 DOM 树

Dherman 的回答中,可以调用

var elements = document.querySelectorAll(':hover');

但是,这假设只有子元素会覆盖它们的祖先(通常是这种情况) ,但一般情况下并非如此,特别是在处理 SVG 时,DOM 树的不同分支中的元素可能会相互重叠。

“视觉”方法——基于“视觉”重叠

这个方法使用 document.elementFromPoint(x, y)来查找最上面的元素,暂时隐藏它(因为我们立即在相同的上下文中恢复它,所以浏览器实际上不会呈现它) ,然后继续查找第二个最上面的元素... ... 看起来有点古怪,但它返回的是你所期望的,例如,树中的兄弟元素相互遮挡。详情请参阅 这篇文章,

function allElementsFromPoint(x, y) {
var element, elements = [];
var old_visibility = [];
while (true) {
element = document.elementFromPoint(x, y);
if (!element || element === document.documentElement) {
break;
}
elements.push(element);
old_visibility.push(element.style.visibility);
element.style.visibility = 'hidden'; // Temporarily hide the element (without changing the layout)
}
for (var k = 0; k < elements.length; k++) {
elements[k].style.visibility = old_visibility[k];
}
elements.reverse();
return elements;
}

尝试两种方法,并检查它们的不同返回值。

当鼠标移动时,mousemove DOM 事件的目标是光标下最顶端的 DOM 元素:

(function(){
//Don't fire multiple times in a row for the same element
var prevTarget=null;
document.addEventListener('mousemove', function(e) {
//This will be the top-most DOM element under cursor
var target=e.target;
if(target!==prevTarget){
console.log(target);
prevTarget=target;
}
});
})();

这与@Philip Walton 的解决方案类似,但不需要 jQuery 或 setInterval。

elementFromPoint()只获取 DOM 树中的第一个元素。这对于开发人员的需求来说大部分是 没有。要在当前鼠标指针位置获取多个元素,需要的函数如下:

document.elementsFromPoint(x, y) . // Mind the 's' in elements

这将返回给定点下所有元素对象的数组。 只需将鼠标 X 和 Y 值传递给这个函数。

更多信息请看: DocumentOrShadowRoot.elementsFromPoint ()

对于不支持的非常老的浏览器,您可以使用 这个答案作为备用。

下面的代码将帮助您获取鼠标指针的元素。生成的元素将显示在控制台中。

document.addEventListener('mousemove', function(e) {
console.log(document.elementFromPoint(e.pageX, e.pageY));
})

您可以使用这个选择器来鼠标下方的对象,然后操作它作为一个 jQuery 对象:

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

对于那些可能仍在挣扎的人,这里有一个解决方案。您希望在希望检测到的子元素的“父”元素上添加一个 mouseover事件。下面的代码向您展示了如何实现它。

const wrapper = document.getElementById('wrapper') //parent element
const position = document.getElementById("displaySelection")


wrapper.addEventListener('mousemove', function(e) {
let elementPointed = document.elementFromPoint(e.clientX, e.clientY)


console.log(elementPointed)
});

CodePen 演示

演示: D

在代码片段窗口中移动鼠标: D

<script>
document.addEventListener('mouseover', function (e) {
console.log ("You are in ", e.target.tagName);
});
</script>

2022年更新:

document.elementsFromPoint()(注意元素中的“ s”)与所有主要浏览器兼容。它基本上与 elementFrompoint做同样的事情,但是按照 DOM 顺序检索所有元素。

Mozilla 有一个很好的例子:

超文本标示语言

<div>
<p>Some text</p>
</div>
<p>Elements at point 30, 20:</p>
<div id="output"></div>

JavaScript

let output = document.getElementById("output");
if (document.elementsFromPoint) {
let elements = document.elementsFromPoint(30, 20);
for (var i = 0; i < elements.length; i++) {
output.textContent += elements[i].localName;
if (i < elements.length - 1) {
output.textContent += " < ";
}
}
} else {
output.innerHTML = "<span style=\"color: red;\">" +
"Browser does not support <code>document.elementsFromPoint()</code>" +
"</span>";
}

输出

Some text


Elements at point 30, 20:


p < div < body < html

Https://developer.mozilla.org/en-us/docs/web/api/document/elementsfrompoint