如何检测鼠标何时离开窗口?


102

我希望能够检测到鼠标何时离开窗口,以便在用户的鼠标位于其他位置时停止触发事件。

有关如何执行此操作的任何想法?


1
看看这个beeker出口意图github库。这很棒。github.com/beeker1121/exit-intent-popup
raksheetbhat

使用mouseleave来防止像mouseout一样触发所有元素:很好的解释和支持:developer.mozilla.org/en-US/docs/Web/API/Element/…–

在文档上设置事件-而不是document.body,以防止火灾滚动条。Windows滚动条似乎使身体收缩。

Answers:


100

请记住,我的答案已经老了很多。

在html页面上实现拖放行为时,通常需要这种行为。以下解决方案已在MS Windows XP计算机上的IE 8.0.6,FireFox 3.6.6,Opera 10.53和Safari 4上进行了测试。
首先是Peter-Paul Koch的一些功能。跨浏览器事件处理程序:

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解决了我获取此事件的问题。谢谢!
杰伊2010年

当未在Chrome中按鼠标时,这似乎不会触发。在chrome中按下鼠标时会触发。似乎是不一致的行为。
2014年

5
如果其他HTML元素正在填充窗口,则此方法将无效。
伊曼纽尔

该解决方案的问题在于,即使用户只是尝试使用滚动条,它也会警告左窗口。我在这里发布了针对此问题的解决方案,但是仍然有一个问题需要解决(请参阅链接)。
JohnyFree,2015年

1
使用mouseleave而不是mouseout可以防止文档中的元素着火。很好的解释,它适用于IE5.5 ... developer.mozilla.org/zh-CN/docs/Web/API/Element/…–

42

如果您使用的是jQuery,那么这段简短又可爱的代码-

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

只要鼠标不在您想要的页面中,就会触发此事件。只需更改功能即可执行任何操作。

您还可以使用:

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

在鼠标再次回到页面时触发。

资料来源:https : //stackoverflow.com/a/16029966/895724


mouseleave工作正常,但是如果打开检查元素也会触发,如何防止?理念?
Pankaj Verma

此技术在Chrome 15至56(我当前的版本)中不稳定。但是它在Firefox中非常有用。请参阅:stackoverflow.com/questions/7448468/...
Tremours

mouseleave似乎开火得多。
亚历山大

如果窗口处于背景中(浏览器未聚焦)并且鼠标进入窗口(Chrome 61 / macOS10.11)
也会

1
@Skeets(及未来的读者)此问题已标记为已修复,截至2019
Xandor

27

这对我有用:

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

9
什么addEvent
Yi Jiang


4
在ie8上,undefinedTarget未定义,在ie9 +和firefox上,toElement未定义。因此,正确的评估结果是:if(((evt.relatedTarget === null)||(evt.toElement === null)){
carlos

1
谓词可以更简洁,如if (!evt.toElement && !evt.relatedTarget)
帕维尔叶

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

========================编辑========================= ======

在新的Firefox版本上似乎未触发document.addEventListener(“ mouseleave”),需要将mouseleave附加到诸如body或child元素之类的元素上。

我建议改用

document.body.addEventListener("mouseleave")

要么

window.addEventListener("mouseout")

时不时被解雇。当由光标移动的目标边界触发的点流中的一个点流并且光标变为调整大小时,类似的接缝将失败。
伊万·波什乔夫

@ 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!') };使用:不要使用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');
    }

});

我将其用于拖放文件上传小部件。它不是绝对准确的,是在鼠标距窗口边缘一定距离时触发的。


我相信,如果鼠标移动“足够快”,这有时不会触发。
约翰·魏茨

@JohnWeisz是的,我认为您是对的。我已经使用此脚本一段时间了,但是效果很好。
伊曼纽尔

6

我已经尝试了以上所有方法,但是似乎没有预期的效果。一个小小的研究后,我发现,e.relatedTargetHTML只是鼠标退出窗口前

所以...我最终得到了这个:


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上拥有该事件,因为Windows滚动条可能会缩小该事件并启动滚动。为何当您具有“ ouseaveave”功能时,为什么在所有冒泡的元素上都会触发“ 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";   
    }

}

适用于Chrome,Firefox,Opera。Aint在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
抱歉,Dan试图解释一个阻止事件传播的元素将阻止事件到达文档/窗口,从而使您的解决方案无效。
詹姆斯

我只是使用其他元素通过自己的onmousemove和onmouseout事件对其进行了测试,但仍然可以正常工作。
奥兹(Ozzy)

2
是的,但是我们再次谈论事件传播。如果您故意使用EVENT.stopPropagation()停止事件传播(对于IE,EVENT.cancelBubble = true),则它不会冒泡到文档/窗口中。要解决此问题,您可以在支持它的浏览器中使用事件捕获。
詹姆斯

请记住,在JS中声明变量,必须使用'var'。现在变量$ span是一个隐式全局变量,可能不是您想要的。同样,如果不是故意的,则不需要使用$作为变量名。
Jani Hartikainen'7

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是使用FOR和FOR javascript编写的吗?
Milche Patern '16

2
@MilchePatern我差不多两年前写了这个答案。那时我还很无知,我没有意识到事实上用jQuery完成的任何事情都可以用纯JavaScript完成。我将更新答案...
www139 2016年

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>")

在这里,您会看到浏览器支持

我以为那很短

但是仍然存在问题,因为“ mouseout”触发了文档中的所有元素

为防止这种情况发生,请使用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,因为当您要滚动而不希望触发mouseLeave事件时,如果鼠标指针悬停在滚动条上,则Windows滚动条可能会收缩主体并触发。document如示例中所示,将其设置为on 。


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较旧的版本,当另一个元素获得焦点时/之后,“模糊”事件是DOM编写的,对于gooChrome,这是元素本身失去焦点的时间。
米歇尔·帕特恩

聪明地使用window.onblur。+1
Redwolf节目

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

这可能有点骇人听闻,但只有在鼠标离开窗口时才会触发。我一直赶上儿童活动,这解决了它



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

请参阅mouseovermouseout

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

这将适用于Chrome浏览器,

$(document).bind('dragleave', function (e) {
    if (e.originalEvent.clientX == 0){
        alert("left window");
    }
});
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.