【问题标题】:Determine which element the mouse pointer is on top of in JavaScript在 JavaScript 中确定鼠标指针位于哪个元素之上
【发布时间】:2012-02-07 10:36:08
【问题描述】:

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

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

【问题讨论】:

    标签: javascript dom mouse


    【解决方案1】:

    DEMO

    有一个非常酷的函数叫做document.elementFromPoint,它听起来像。

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

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

    document.elementFromPoint

    jQuery event object

    【讨论】:

    • @TikhonJelvis:嗯,来自here 我看到它在 IE 和 firefox 上受支持。如果你得到这两个,你通常会得到它们。 MSDNMDN
    • 太棒了。有没有办法在不捕捉事件的情况下获得鼠标的坐标? (可能不是我假设)。如果这不可能,那么不幸的是,我认为这种方法并不比event.target 或其他任何方法更好
    • @HoraceLoeb 在不捕获事件的情况下无法获取鼠标坐标。更多解释见this SO question
    • 这是一种奇怪的做法。如果你捕捉到一个事件,为什么不直接使用event.target 呢?
    • 答案没有解释event 是什么,以及它是如何形成的
    【解决方案2】:

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

    document.querySelectorAll( ":hover" );
    

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

    【讨论】:

    • 当我在其他 <li> 元素之上拖动 <li> 时,这似乎不起作用。
    • 我用 $(':hover') 创建了一个小提琴,但它基本上是一样的:jsfiddle.net/pmrotule/2pks4tf6
    • (function(){ var q = document.querySelectorAll(":hover"); return q[q.length-1]; })()
    • 我感觉这种表现很糟糕。在mousemove 上调用它可能会损害性能
    【解决方案3】:

    尽管以下内容可能实际上并没有回答问题,因为这是谷歌搜索的第一个结果(谷歌人可能不会问完全相同的问题:),但希望它会提供一些额外的输入。

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

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

    dherman's answer,可以拨打电话

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

    但是,这假设只有子级会覆盖他们的祖先,这通常是这种情况,但通常情况并非如此,尤其是在处理 SVG 时,DOM 树的不同分支中的元素可能相互重叠。

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

    这个方法使用document.elementFromPoint(x, y)找到最顶层的元素,暂时隐藏它(因为我们在相同的上下文中立即恢复它,浏览器实际上不会渲染它),然后继续寻找第二个最顶层的元素......看起来有点 hacky,但是当树中的兄弟元素相互遮挡时,它会返回您所期望的结果。详情请找this post

    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。令人惊讶的是,您的代码也处理嵌套子元素的情况。
    • 这非常有用。正是我想要的。正如您所说,querySelectorAll 并非在所有情况下都有效。
    • @herrlich10 对于developer.mozilla.org/en-US/docs/Web/API/Document/…,这似乎是一个不错的polyfill。如果您支持的 browserSet 中存在该 API,我认为您可以使用它。
    • BUG:当可见性被动画化时,最终进入无限循环,例如。当transition: all 1s;被使用
    • Document.elementsFromPoint(x, y)stackoverflow.com/a/31805883/1059828
    【解决方案4】:

    elementFromPoint() 仅获取 DOM 树中的第一个元素。对于开发人员的需求,这主要不够。要获得多个元素,例如当前鼠标指针位置,这是你需要的函数:

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

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

    更多信息在这里:DocumentOrShadowRoot.elementsFromPoint()

    对于不支持的非常旧的浏览器,您可以使用this answer 作为备用。

    【讨论】:

    • 现在在2018年得到很好的支持。
    【解决方案5】:

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

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

    【讨论】:

    • 这需要光标移动。尽可能接近,这不是这里要问的。
    • 页面滚动时不起作用。请改用 e.clientXe.clientY(在 Firefox 59 上测试)。
    【解决方案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) 更昂贵的资源。
    【解决方案7】:

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

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

    Here’s a demo.

    【讨论】:

      【解决方案8】:

      演示 :D

      在 sn-p 窗口中移动鼠标 :D

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

      【讨论】:

        【解决方案9】:
        <!-- 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. -->
        

        【讨论】:

        • 对于您在(现已删除)问题上受到的不当对待,我深表歉意。就个人而言,我更愿意取消删除这个问题。虽然它正在关闭的路上(在我看来,这是不公平的),但我正计划投票重新打开它。但是,鉴于反对票的数量,我理解您是否选择将其删除。
        【解决方案10】:

        你可以使用这个选择器来控制对象,然后将它作为一个 jQuery 对象来操作:

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

        【讨论】:

        • 欢迎来到 Stack Overflow!请添加一些解释为什么此代码有助于 OP。这将有助于为未来的观众提供一个可以从中学习的答案。请参阅How to Answer 了解更多信息。还有,“undermouse”?
        • 什么是"toundermouse object"?您的意思是“对鼠标下的对象”?还是别的什么?
        【解决方案11】:

        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。

        【讨论】:

          【解决方案12】:

          对于那些可能仍在苦苦挣扎的人来说,这是一个解决方案。您想在要检测的子元素的“父”元素上添加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)
          });
          

          Demo on CodePen

          【讨论】:

            【解决方案13】:

            首先让我说我不建议使用我将要建议的方法。最好使用事件驱动开发并将事件仅绑定到您有兴趣知道鼠标是否结束的元素,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/

            【讨论】:

              猜你喜欢
              • 2011-04-27
              • 1970-01-01
              • 1970-01-01
              • 2018-02-05
              • 1970-01-01
              • 1970-01-01
              • 2011-04-18
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多