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


109

マウスカーソルが置かれている要素を通知する関数が必要です。

したがって、たとえば、ユーザーのマウスが(idを使用してwmd-input)このテキストエリア上にある場合、呼び出しwindow.which_element_is_the_mouse_on()は機能的には次のようになります。$("#wmd-input")

回答:


147

デモ

document.elementFromPointそれがどのように聞こえるかを実行する呼ばれる本当にクールな関数があります。

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

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

document.elementFromPoint

jQueryイベントオブジェクト


1
@TikhonJelvis:IEとFirefoxでサポートされていることがわかります。これらの2つを取得した場合、通常はすべてを取得します。MSDN MDN
qwertymk '11

1
驚くばかり。イベントをキャッチせずにマウスの座標を取得する方法はありますか?(おそらく私は想定していません)。これが不可能な場合には、残念ながら私はこの方法がどれよりも優れているとは思わないevent.targetか何
トム・レーマン

1
@HoraceLoebイベントをキャッチせずにマウスの座標を取得することはできません。詳細については、このSOの質問を参照してください
Logan Besecker '16

2
それは奇妙な方法です。イベントをキャッチしたら、単に使用しないのはなぜevent.targetですか?
pmrotule 2015年

3
答えは何であるかevent、およびそれがどのようになったかを説明していません
vsync

64

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

document.querySelectorAll( ":hover" );

これにより、マウスが現在ドキュメントの上にある項目のNodeListが表示されます。NodeListの最後の要素は最も具体的であり、先行する各要素は親、祖父母などである必要があります。


2
これは<li>、他の<li>要素の上にしばらくドラッグしている間は機能しなかったようです。
セイリア2014

2
私はフィドルを作成しました$(':hover')が、基本的には同じです:jsfiddle.net/pmrotule/2pks4tf6
pmrotule

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

3
これのパフォーマンスは恐ろしいと感じています。これを呼び出すとmousemoveパフォーマンスが低下する可能性があります
vsync

49

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

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

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

ダーマンの答えと同じように、

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

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

「ビジュアル」アプローチ-「ビジュアル」オーバーラップに基づく

このメソッドは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、2015年

これは非常に便利です。まさに私が探していたもの。既に述べたように、querySelectorAllはすべてのシナリオで機能するわけではありません。
noobsharp 2016年

4
@ herrlich10これはのためのまともなポリフィルのように思えるdeveloper.mozilla.org/en-US/docs/Web/API/Document/...。サポートされているbrowserSetにそのAPIが存在する場合は、それを使用できると思います。
ダーマン

これのおかげで-expetcedとほぼ同じように機能します(ただし、getElementsFromPointとの互換性のためにelements.reverseはありません)。注意(より基本的なイベント駆動型のアプローチを使用できない場合、ドラッグ中にドロップターゲットを見つけることはできません)。
jsdw 2016年

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/en-US/docs/Web/API/document/elementsFromPoint

サポートされていない非常に古いブラウザの場合、この回答をフォールバックとして使用できます。


3
現在、2018年には十分にサポートされています
少年

6

マウスオーバーイベントはバブルするので、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));">

私自身はユニバーサルイベントハンドラーを使用していますが、これはに比べてリソースのコストが高くなりdocument.elementFromPoint(x, y)ます。
ジョン

6

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

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

1
これにはカーソルを移動する必要があります。できる限り近いので、ここで尋ねられていることではありません。
Carles Alcolea

ページがスクロールされている場合は機能しません。代わりにe.clientXおよびe.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)
});

コーデックのデモ

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.