确定鼠标指针在Javascript顶部的哪个元素


109

我想要一个函数来告诉我鼠标光标在哪个元素上。

因此,例如,如果用户的鼠标位于该文本区域(ID为wmd-input)上,则调用window.which_element_is_the_mouse_on()在功能上等同于$("#wmd-input")

Answers:


147

演示

有一个很酷的函数document.elementFromPoint,它听起来像什么。

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

var x = event.clientX, y = event.clientY,
    elementMouseIsOver = document.elementFromPoint(x, y);

document.elementFromPoint

jQuery事件对象


1
@TikhonJelvis:从这里,我看到IE和firefox都支持它。如果得到这两个,通常就全部得到。MSDN MDN
qwertymk 2012年

1
太棒了 有什么办法可以在不捕获事件的情况下获得鼠标的坐标?(可能不是我想的)。如果这是不可能的,那么很不幸,我不认为这种方法是任何优于event.target或什么
汤姆-雷曼

1
@HoraceLoeb不捕获事件就不可能获得鼠标坐标。看到这个SO问题以获取进一步的解释
Logan Besecker 2012年

2
这是一种奇怪的方式。如果您赶上事件,为什么不只使用event.target
pmrotule 2015年

3
答案没有解释什么event是什么,以及它是如何变成的
vsync

64

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

document.querySelectorAll( ":hover" );

这将为您提供一个NodeList,它按文档顺序显示鼠标当前位于的项目。NodeList中的最后一个元素是最具体的,前面的每个元素都应该是父级,祖父母级,依此类推。


2
当我<li>在其他<li>元素上拖动一会儿时,这似乎不起作用。
Seiyria 2014年

2
我创建了一个小提琴,$(':hover')但是基本上是一样的:jsfiddle.net/pmrotule/2pks4tf6
pmrotule 2015年

3
(function(){ var q = document.querySelectorAll(":hover"); return q[q.length-1]; })()
用户

3
我感觉这种性能太糟糕了。调用它mousemove可能会损害性能
vsync

49

尽管以下内容可能并未真正回答问题,但由于这是谷歌搜索的第一个结果(Google员工可能不会问完全相同的问题:),希望它会提供一些额外的输入。

实际上,有两种方法可以获取鼠标当前所处的所有元素的列表(也许对于较新的浏览器而言):

“结构”方法-升序DOM树

就像德曼的回答一样,

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

尝试两者,并检查它们的不同收益。


这对我很有帮助。谢谢@ herrlich10。令人惊讶的是,您的代码也使用嵌套的子元素来处理情况。
Vikram Deshmukh

这是非常有用的。正是我想要的。如您所说,querySelectorAll并非在每种情况下都适用。
noobsharp

4
@ herrlich10对于developer.mozilla.org/en-US/docs/Web/API/Document / ...来说,这似乎是一个不错的polyfill 。如果您支持的browserSet中存在该API,我想您可以使用它。
dherman '16

谢谢你的付出-工作原理差不多(尽管没有element.reverse可以与getElementsFromPoint兼容),但是它的速度很慢(在chrome测试中,每次调用18-20ms),这使得我在这种情况下很难使用注意(在使用更基本的事件驱动方法的情况下,在拖动过程中找到放置目标是不可行的)。
jsdw

1
参见Document.elementsFromPoint(x, y) stackoverflow.com/a/31805883/1059828
Karl Adler,

21

elementFromPoint()仅获取DOM树中的第一个元素。这几乎不足以满足开发人员的需求。要在当前鼠标指针位置获得多个元素,这是您需要的功能:

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

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

此处的更多信息:https : //developer.mozilla.org/zh-CN/docs/Web/API/document/elementsFromPoint

对于不支持的非常旧的浏览器,您可以将此答案用作备用。


3
现在在2018
Boy

6

鼠标悬停事件冒泡,因此您可以将单个侦听器放在主体上,等待它们冒泡,然后抓住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.elementFromPoint(x, y)
约翰

6

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

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

1
这需要光标移动。尽可能接近,这不是这里要问的。
卡尔斯·阿尔科利亚

如果页面滚动,则不起作用。使用e.clientXe.clientY代替(在Firefox 59上测试)。
youen

5

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

var currentElement = null;

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

这是一个演示。


4
<!-- 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. -->

3
抱歉,您对(现在已删除)问题的处理态度很差。我个人希望这个问题不被删除。当它即将关闭时(我认为这是不公平的),我正计划投票决定重新开放它。但是,考虑到弃权票的数量,我知道您是否选择将其删除。
2015年

3

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

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


1

mousemoveDOM事件的目标是鼠标移动时光标下方的最上面的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。


1

您可以使用此选择器在对象上添加鼠标,然后将其作为jquery对象操作。 $(':hover').last();


4
欢迎使用Stack Overflow!请添加一些解释,说明此代码为何有助于OP。这将为将来的观众提供借鉴。有关更多信息,请参见如何回答。还有,“鼠标不足”?
异端猴

0

首先,我要说的是我不建议使用我将建议的方法。这是更好的使用事件驱动的开发和绑定的事件只有你有兴趣了解鼠标是否是在与元素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/


0

古老的问题,但是这里为那些仍在挣扎中的人们提供了解决方案。您想要在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上的演示

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.