web-dev-qa-db-ja.com

JavaScriptでマウスポインターが上にある要素を特定する

マウスカーソルがどの要素の上にあるかを示す関数が必要です。

そのため、たとえば、ユーザーのマウスがこのテキスト領域(ID wmd-input)上にある場合、window.which_element_is_the_mouse_on()を呼び出すことは$("#wmd-input")と機能的に同等です。

94
Tom Lehman

DEMO

document.elementFromPointと呼ばれる非常にクールな関数がありますが、これはそのように聞こえます。

必要なのは、マウスのxおよびy座標を見つけて、それらの値を使用して呼び出すことです。

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

document.elementFromPoint

jQueryイベントオブジェクト

130
qwertymk

新しいブラウザでは、次のことができます。

document.querySelectorAll( ":hover" );

これにより、マウスが現在ドキュメントの順序で上にあるアイテムのNodeListが表示されます。 NodeListの最後の要素は最も具体的であり、先行する各要素は親、祖父母などでなければなりません。

58
dherman

以下は実際に質問に答えていない可能性がありますが、これはグーグルの最初の結果なので(グーグルはまったく同じ質問をしないかもしれません)、追加の入力を提供してくれることを願っています。

実際、マウスが現在置かれているすべての要素のリストを取得するには、2つの異なるアプローチがあります(おそらく、新しいブラウザーの場合)。

「構造」アプローチ-昇順DOMツリー

ダーマンの答えのように、電話することができます

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

ただし、これは通常、子のみが祖先をオーバーレイすることを前提としていますが、通常はそうではありませんが、特にDOMツリーの異なるブランチの要素が互いにオーバーラップする可能性があるSVGを扱う場合はそうではありません。

「視覚的」アプローチ-「視覚的」重複に基づく

このメソッドはdocument.elementFromPoint(x, y)を使用して最上位の要素を見つけ、一時的に非表示にし(同じコンテキストですぐに復元するため、ブラウザは実際にこれをレンダリングしません)、次に2番目の最上位の要素を検索します...少しハッキーですが、たとえばツリー内に兄弟要素がお互いを閉塞している場合など、期待するものを返します。詳しくは この投稿 をご覧ください。

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

両方試して、それぞれの返品を確認してください。

44
herrlich10

elementFromPoint()は、DOMツリーの最初の要素のみを取得します。これは開発者のニーズにはほとんど十分ではありません。したがって、このNice関数はありません。

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

これは、指定されたポイントの下にあるすべての要素オブジェクトの配列を返します。

これをサポートしていない古いブラウザの場合、 this answer をフォールバックとして使用できます

古いブラウザの互換性に関する詳細はこちら: https://developer.mozilla.org/en-US/docs/Web/API/document/elementsFromPoint

9
Karl Adler

マウスオーバーイベントがバブルするため、1人のリスナーをボディに配置して、バブルが発生するのを待ってから、event.targetまたはevent.srcElementを取得できます。

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

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

適切な祖先のmouseoverイベントのターゲットを確認できます。

var currentElement = null;

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

デモはこちら

4
Ry-

次のコードは、マウスポインターの要素を取得するのに役立ちます。結果の要素がコンソールに表示されます。

document.addEventListener('mousemove', function(e) {
    console.log(document.elementFromPoint(e.pageX, e.pageY)); 
})
4
saikumar
<!-- 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. -->
4
Dip M

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を必要としません。

1
Max Heiber

このセレクターを使用してオブジェクトをアンダーマウス化し、jqueryオブジェクトとして操作することができます。 $(':hover').last();

1
Serge Gordeev

私が提案しようとしている方法を使用することはお勧めできないと言って始めましょう。イベント駆動開発を使用し、マウスが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
Philip Walton

古い質問ですが、まだ苦労している可能性のある人のための解決策があります。検出する子要素の「親」要素に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のデモ

0
UZOR

デモ:Dスニペットウィンドウでマウスを動かします:D

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