マウスがウィンドウから離れたときはどうすれば検出できますか?


102

ユーザーのマウスが他の場所にあるときにイベントが発生するのを停止できるように、マウスがウィンドウを離れたときにそれを検出できるようにしたいと考えています。

これを行う方法のアイデアはありますか?


1
このビーカーの出口を意図したgithubライブラリーを調べてください。それは素晴らしい。github.com/beeker1121/exit-intent-popup
raksheetbhat

使用すると、mouseleaveとして、すべての要素に発射を防止するためにマウスアウトは非常に良い説明とサポートを::ないdeveloper.mozilla.org/en-US/docs/Web/API/Element/...

document.bodyではなく、ドキュメントにイベントを設定して、スクロールバーが起動しないようにします。Windowsのスクロールバーが本体を縮小しているようです。

回答:


100

私の回答はかなり古くなっています。

このタイプの動作は、HTMLページにドラッグアンドドロップ動作を実装するときに通常は必要です。以下のソリューションは、MS Windows XPマシン上のIE 8.0.6、FireFox 3.6.6、Opera 10.53、およびSafari 4でテストされています。
最初にピーターポールコッホから少し関数; クロスブラウザーイベントハンドラー:

function addEvent(obj, evt, fn) {
    if (obj.addEventListener) {
        obj.addEventListener(evt, fn, false);
    }
    else if (obj.attachEvent) {
        obj.attachEvent("on" + evt, fn);
    }
}

次に、このメソッドを使用して、イベントハンドラーをドキュメントオブジェクトのmouseoutイベントにアタッチします。

addEvent(document, "mouseout", function(e) {
    e = e ? e : window.event;
    var from = e.relatedTarget || e.toElement;
    if (!from || from.nodeName == "HTML") {
        // stop your drag event here
        // for now we can just use an alert
        alert("left window");
    }
});

最後に、デバッグ用のスクリプトが埋め込まれたHTMLページを次に示します。

<html>
<head>
<script type="text/javascript">
function addEvent(obj, evt, fn) {
    if (obj.addEventListener) {
        obj.addEventListener(evt, fn, false);
    }
    else if (obj.attachEvent) {
        obj.attachEvent("on" + evt, fn);
    }
}
addEvent(window,"load",function(e) {
    addEvent(document, "mouseout", function(e) {
        e = e ? e : window.event;
        var from = e.relatedTarget || e.toElement;
        if (!from || from.nodeName == "HTML") {
            // stop your drag event here
            // for now we can just use an alert
            alert("left window");
        }
    });
});
</script>
</head>
<body></body>
</html>

window.eventを使用して、このイベントの取得に関する問題を修正しました。ありがとう!
Jay

マウスがクロムで押されていない場合、これは起動しないように見えます。マウスがクロムで押されたときに発生します。一貫性のない動作のようです。
antony.trupe 2014年

5
他のHTML要素がウィンドウを埋めている場合、これは機能しません。
Emmanuel 14

このソリューションの問題は、ユーザーがスクローラーを使用しようとした場合でも、左側のウィンドウに警告することです。この問題の解決策をここに公開しましたが、解決する必要のある問題がまだ1つあります(リンクを参照)。
JohnyFree、2015年

1
マウスアウトの代わりにマウスリーブを使用して、ドキュメント内の要素が発火しないようにします。非常に良い説明と、それはIE5.5 ...上で動作しますdeveloper.mozilla.org/en-US/docs/Web/API/Element/...

41

あなたがjQueryを使用しているなら、この短くて甘いコードはどうですか-

$(document).mouseleave(function () {
    console.log('out');
});

このイベントは、マウスが目的のページにない場合にトリガーされます。関数を変更して、好きなことを実行できます。

そして、あなたも使うことができます:

$(document).mouseenter(function () {
    console.log('in');
});

マウスが再びページに戻ったときにトリガーします。

ソース:https : //stackoverflow.com/a/16029966/895724


mouseleaveは機能していますが、inspect要素が開かれている場合にも発火しています。考え?
Pankaj Verma 2017年

この手法はChrome 15〜56(現在のバージョン)では安定していません。しかし、これはFirefoxで非常に機能します。参照:stackoverflow.com/questions/7448468/...
Tremours

マウスリーブは必要以上に発砲するようです。
アレクサンダー

また、ウィンドウがバックグラウンドにあり(ブラウザーがフォーカスされていない)、マウスがウィンドウに入った場合(Chrome 61 / macOS10.11)
CodeBrauer

1
@Skeets(および将来のリーダー)この問題は、2019年2月14日のとして固定マークされている
XANDOR

27

これは私にとってはうまくいきます:

addEvent(document, 'mouseout', function(evt) {
  if (evt.toElement == null && evt.relatedTarget == null) {
    alert("left window");
  }
});

9
なにaddEvent
Yi Jiang


4
ie8では、relatedTargetは未定義であり、ie9 +およびfirefoxでは、toElementは未定義です。そのため、正しい評価は次のようになります:if((evt.relatedTarget === null)||(evt.toElement === null)){
carlos

1
述語は次のように簡潔にすることができますif (!evt.toElement && !evt.relatedTarget)
Pavel Ye

20

スクロールバーとautcompleteフィールドを考慮せずにmouseleaveを検出するか、検査するには:

document.addEventListener("mouseleave", function(event){

  if(event.clientY <= 0 || event.clientX <= 0 || (event.clientX >= window.innerWidth || event.clientY >= window.innerHeight))
  {

     console.log("I'm out");

  }
});

条件の説明:

event.clientY <= 0  is when the mouse leave from the top
event.clientX <= 0  is when the mouse leave from the left
event.clientX >= window.innerWidth is when the mouse leave from the right
event.clientY >= window.innerHeight is when the mouse leave from the bottom

======================== EDIT ========================= ======

document.addEventListener( "mouseleave")は、Firefoxの新しいバージョンでは発生しないようです。mouseleaveは、bodyなどの要素または子要素にアタッチする必要があります。

代わりに使用することをお勧めします

document.body.addEventListener("mouseleave")

または

window.addEventListener("mouseout")

時々解雇されていません。カーソルの移動によってトリガーされたポイントストリームの1ポイントが境界線を狙い、カーソルのサイズが変更されると、シームが失敗するように見えます。
Ivan Borshchov

@ user3479125、私のスニペットでも試してみて、ifステートメントが追加されていないときに問題が解決するかどうか確認してください。それはスクロールバーを考慮に入れますが、私はオートコンプリートまたは検査でテストしていません。stackoverflow.com/a/56678357/985399

7

onMouseLeaveイベントを使用すると、バブリングが防止され、マウスがブラウザウィンドウを離れたときに簡単に検出できます。

<html onmouseleave="alert('You left!')"></html>

http://www.w3schools.com/jsref/event_onmouseleave.asp


素晴らしい!サポートはIE5.5 +です...動作します:document.onmouseleave = function() { alert('You left!') };本体を縮小するaboweスクロールバーを起動するdocument.bodyを使用しないでください!要素の発火を防ぐためのコードは必要ありません。良い説明:developer.mozilla.org/en-US/docs/Web/API/Element/…–

6

これらの答えはどれもうまくいきませんでした。私は今使っています:

document.addEventListener('dragleave', function(e){

    var top = e.pageY;
    var right = document.body.clientWidth - e.pageX;
    var bottom = document.body.clientHeight - e.pageY;
    var left = e.pageX;

    if(top < 10 || right < 20 || bottom < 10 || left < 10){
        console.log('Mouse has moved out of window');
    }

});

これをドラッグアンドドロップファイルアップロードウィジェットに使用しています。マウスがウィンドウの端から特定の距離に近づくとトリガーされるため、完全に正確ではありません。


マウスの動きが「十分に速い」場合、これはトリガーされないことがあります。
John Weisz 2017

@JohnWeiszはい、私はあなたが正しいと思います。私はしばらくの間このスクリプトを使用してきましたが、それでもうまくいきます。
Emmanuel

6

上記をすべて試しましたが、期待どおりに動作するようには見えません。少し調べたところ、e.relatedTarget、マウスがウィンドウから出る直前のhtmlであることがわかりました。

だから...私はこれで終わりました:


document.body.addEventListener('mouseout', function(e) {
    if (e.relatedTarget === document.querySelector('html')) {
        console.log('We\'re OUT !');
    }
});

問題や改善点がありましたらお知らせください。

2019アップデート

(user1084282が発見したように)

document.body.addEventListener('mouseout', function(e) {
    if (!e.relatedTarget && !e.toElement) {
        console.log('We\'re OUT !');
    }
});

2
Chromeで私のために働いていません。relatedTargetマウスがウィンドウから離れるとnullになります。@ user1084282の回答に触発されて、これを次のように変更します。if(!e.relatedTarget && !e.toElement) { ... }これは機能します

if(!e.relatedTarget && !e.toElement)実際の回答で条件の代わりに使用した場合、これはChrome、Firefox、IE Edgeで正常に機能することを確認しました。文書から離れたマウスを検出します。
Haijerome

ウィンドウのスクロールバーがイベントを縮小し、スクロールを起動する可能性があるため、document.bodyにイベントを設定しないでください。そして、「mouseleave」を使用できるときに、すべてのバブル要素で発生する「mouseout」があるのはなぜですか。 developer.mozilla.org/en-US/docs/Web/API/Element/...

2

私が言ったことを取り戻します。可能です。私はこのコードを書き、完全に動作しました。

window.onload = function() {

    $span = document.getElementById('text');

    window.onmouseout = function() {
        $span.innerHTML = "mouse out";  
    }

    window.onmousemove = function() {
        $span.innerHTML = "mouse in";   
    }

}

クロム、Firefox、オペラで動作します。IEではテストされていませんが、動作することを前提としています。

編集。IEはいつも問題を引き起こします。IEで機能させるには、イベントをウィンドウからドキュメントに置き換えます。

window.onload = function() {

    $span = document.getElementById('text');

    document.onmousemove = function() {
        $span.innerHTML = "mouse move";
    }

    document.onmouseout = function() {
        $span.innerHTML = "mouse out";
    }

}

それらを組み合わせて、クロスブラウザキックアスカーソル検出o0:P


これがページの要素とどのように連携するかをテストしましたか?独自の「onmouseover / out」イベントを持つ要素は、バブリングをキャンセルしてこの機能を壊す可能性があると思います。
ダンハーバート

1
Ozzy、Danは、イベントの伝播を停止する要素はイベントがドキュメント/ウィンドウに到達することを妨げ、それによってソリューションを無効にすることを説明しようとしています。
ジェームズ

独自のonmousemoveイベントとonmouseoutイベントを使用して他の要素でテストしたところ、まだ正常に動作しています。
Ozzy、

2
はい、大丈夫ですが、ここでもイベントの伝播について話しています。EVENT.stopPropagation()(IEの場合、EVENT.cancelBubble = true)を使用して意図的にイベントの伝播を停止すると、ドキュメント/ウィンドウまでバブルアップしません...これに対抗するには、それをサポートするブラウザーでイベントキャプチャーを使用できます。 。
ジェームズ

JSで変数を宣言するには、「var」を使用する必要があることに注意してください。ここで、変数$ spanは暗黙のグローバルです。これはおそらく望んでいるものではありません。また、意図的でない場合は、変数名に$は必要ありません。
Jani Hartikainen

2

このCSSを適用してください:

html
{
height:100%;
}

これにより、html要素がウィンドウの高さ全体を占めるようになります。

このjqueryを適用します。

$("html").mouseleave(function(){
 alert('mouse out');
});

mouseoverとmouseoutの問題は、htmlからマウスオーバー/アウトして子要素にすると、イベントが開始されることです。私が与えた機能、子要素にマウスを置いたときにオフになりません。ウィンドウからマウスで出たり入ったりしたときにのみオフになります

ユーザーがウィンドウ内でマウスを使ったときにできることを知っているだけです。

$("html").mouseenter(function(){
  alert('mouse enter');
});

2
「JavaScriptに同等の機能があるとは思わない」とは、jQueryがJavaScript関数ライブラリであり、jQueryがWITHおよびFOR JavaScriptで記述されていることを知らないということです。
Milche Patern 2016

2
@MilchePatern私がこの回答を書いたのは、ほぼ2年前のことです。当時は無知だったので、jQueryで実行できることはすべて純粋なJavaScriptで実行できるという事実を知りませんでした。答えを更新します...
www139

2

私は次々と試し、その時に最良の答えを見つけました:

https://stackoverflow.com/a/3187524/985399

古いブラウザをスキップするため、最新のブラウザ(IE9 +)で動作するようにコードを短くしました

    document.addEventListener("mouseout", function(e) {
        let t = e.relatedTarget || e.toElement;
        if (!t || t.nodeName == "HTML") {
          console.log("left window");
        }
    });

document.write("<br><br>PROBLEM<br><br><div>Mouseout trigg on HTML elements</div>")

ここに表示されます ブラウザのサポート

それはかなり短かったと思いました

しかし、「マウスアウト」がドキュメントのすべての要素をトリガーするため、問題はまだ残っています

それが起こらないようにするには、mouseleaveを使用してください(IE5.5以降)を。リンクの適切な説明を参照してください。

次のコードは、要素の内部または外部の要素をトリガーしなくても機能します。ドキュメントの外にドラッグして解放してみてください。

var x = 0

document.addEventListener("mouseleave", function(e) { console.log(x++) 
})

document.write("<br><br>SOLUTION<br><br><div>Mouseleave do not trigg on HTML elements</div>")

イベントは任意のHTML要素に設定できます。document.bodyただし、イベントはありません。ウィンドウのスクロールバーが本体を縮小し、スクロールしたいがマウスリーブイベントをトリガーしたくないときに、マウスポインターがスクロールバーに曲がっているときに発生する可能性があるためです。document例のように、代わりにオンに設定します。


1

おそらくbodyタグでOnMouseOverを常に聞いている場合は、イベントが発生していないときにコールバックしますが、Zackが述べているように、これは非常に醜い可能性があります。すべてのブラウザが同じようにイベントを処理するわけではないため、同じページのdivの上にいても、MouseOverを失う可能性があります。


答えではありません

1

多分これは後でここに来る人々の一部を助けるでしょう。 window.onblurdocument.mouseout

window.onblur 次の場合にトリガーされます:

  • Ctrl+Tabまたはを使用して別のウィンドウに切り替えますCmd+Tab
  • ドキュメントインスペクターに(マウスオーバーだけでなく)フォーカスします。
  • デスクトップを切り替えます。

基本的に、そのブラウザタブがフォーカスを失ったときはいつでも。

window.onblur = function(){
    console.log("Focus Out!")
}

document.mouseout 次の場合にトリガーされます:

  • カーソルをタイトルバーに移動します。
  • Ctrl+Tabまたはを使用して別のウィンドウに切り替えますCmd+Tab
  • カーソルをドキュメントインスペクターに移動します。

基本的に、カーソルがドキュメントから離れた場合。

document.onmouseleave = function(){
    console.log("Mouse Out!")
}

「そのブラウザのタブがフォーカスを失ったときはいつでも。」.. IEの古いバージョンでは、「blur」イベントは、別の要素がフォーカスを受け取ったとき/後にDOMでコンパイルされます。gooChromeの場合は、要素自体がフォーカスを失うときです。
Milche Patern 2016

スマートな使い方window.onblurも。+1
Redwolfプログラム

1
$(window).mouseleave(function(event) {
  if (event.toElement == null) {
    //Do something
  }
})

これは少しハックかもしれませんが、マウスがウィンドウを離れたときにのみトリガーされます。私は子供のイベントをキャッチし続け、これはそれを解決しました



1

これでうまくいきました。ここにいくつかの答えの組み合わせ。また、モデルを示すコードを1回だけ含めました。そして、モデルは他のどこかをクリックすると消えます。

<script>
    var leave = 0
    //show modal when mouse off of page
    $("html").mouseleave(function() {
       //check for first time
       if (leave < 1) {
          modal.style.display = "block";
          leave = leave + 1;
       }
    });

    // Get the modal with id="id01"
       var modal = document.getElementById('id01');

    // When the user clicks anywhere outside of the modal, close it
       window.onclick = function(event) {
          if (event.target == modal) {
             modal.style.display = "none";
          }
       }
</script>

質問にjQueryタグはありませんでした
mrReiha

jQueryは、最新のブラウザーIE9 +とその他のブラウザーで機能する私の回答と比較すると、多くのコードです。それはこの回答に基づいていますが、はるかに短いです:stackoverflow.com/a/3187524/985399

1

mouseoverおよびを参照してくださいmouseout

var demo = document.getElementById('demo');
document.addEventListener("mouseout", function(e){demo.innerHTML="😞";});
document.addEventListener("mouseover", function(e){demo.innerHTML="😊";});
div { font-size:80vmin; position:absolute;
      left:50%; top:50%; transform:translate(-50%,-50%); }
<div id='demo'>😐</div>


0

私はこれをテストしていませんが、本能はbodyタグでOnMouseOut関数を呼び出すことです。


-2

これはクロームで動作します、

$(document).bind('dragleave', function (e) {
    if (e.originalEvent.clientX == 0){
        alert("left window");
    }
});
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.