Як я можу виявити, коли миша залишає вікно?


102

Я хочу мати змогу виявити, коли миша виходить з вікна, щоб я міг зупинити події від запуску, поки миша користувача знаходиться в іншому місці.

Будь-які ідеї, як це зробити?


1
Ознайомтеся з цією бібліотекою github-виїзду, що спрямована на вихід Це чудово. github.com/beeker1121/exit-intent-popup
raksheetbhat

Використовуйте миші для запобігання стрільбі по всіх елементах, як це робиться у миші : Дуже вдале пояснення та підтримка: developer.mozilla.org/en-US/docs/Web/API/Element/…

Встановити подію на документ - не document.body, щоб запобігти пожежі за межі прокрутки. Панель прокрутки Windows, здається, зменшує тіло.

Відповіді:


100

Будь ласка, майте на увазі, що моя відповідь давно постаріла.

Цей тип поведінки зазвичай бажаний під час реалізації поведінки перетягування на HTML-сторінці. Наведене нижче рішення було протестовано на IE 8.0.6, FireFox 3.6.6, Opera 10.53 та Safari 4 на машині MS Windows XP.
Спочатку невелика функція від Петра-Пола Коха; крос-обробник подій браузера:

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 виправило мою проблему з отриманням цієї події. Дякую!
Джей

схоже, що це не спрацьовує, якщо миша не натискається на хром. він спрацьовує при натисканні миші на хром. здається непослідовною поведінкою.
antony.trupe

5
Це не працює, якщо інші елементи HTML заповнюють вікно.
Еммануїл

Проблема цього рішення полягає в тому, що воно попереджає ліве вікно, навіть якщо користувач просто намагається використовувати скроллер. Я опублікував рішення цієї проблеми тут , але все ж є одна проблема, яку потрібно вирішити (див. Посилання).
JohnyFree

1
Використовуйте мишак замість миші, щоб запобігти загорянню елементів у документі. Дуже добре пояснення, і це працює на IE5.5 ... developer.mozilla.org/en-US/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 працює, але він також стріляє, якщо елемент перевірки відкритий, як запобігти? Ідея?
Панкай Верма

Ця методика не є стабільною в Chrome 15-16 (моя поточна версія). Але у Firefox це дуже добре працює. Див: stackoverflow.com/questions/7448468 / ...
Tremours

мишоловка, здається, вистрілює набагато більше, ніж слід.
Олександр

Він також спрацьовує, якщо вікно знаходиться у фоновому режимі (браузер не зосереджений) і миша заходить у вікно (Chrome 61 / macOS10.11)
CodeBrauer

1
@Skeets (та майбутні читачі) Ця проблема позначена виправленими станом на 14 лютого 2019 р.
Xandor

27

Це працює для мене:

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

9
Що таке addEvent?
Yi Jiang

5
це функція, визначена у відповіді Джошуа Міллса
superjos

4
на ie8, relatedTarget не визначено, на ie9 + і firefox, toElement не визначено. Тому що це правильне оцінювання: якщо ((evt.relatedTarget === null) || (evt.toElement === null)) {
carlos

1
Присудок міг бути більш лаконічним як вif (!evt.toElement && !evt.relatedTarget)
Павло

20

Для того щоб виявити миші, не враховуючи смугу прокрутки та поле автозаповнення або перевірити:

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, миші потрібно приєднати до такого елемента, як body або дочірній елемент.

Я пропоную використовувати замість цього

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.relatedTarget є HTML тільки перед мишею виходить з вікна .

Отже ... я закінчила це:


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

Будь ласка, повідомте мене, якщо ви знайдете якісь проблеми або вдосконалення!

Оновлення 2019 року

(як з'ясував користувач1084282)

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

2
Не працює на хром. relatedTargetє нульовим, коли миша залишає вікно. Натхненний відповіддю @ user1084282, змініть це на це: if(!e.relatedTarget && !e.toElement) { ... }і воно працює

Я підтверджую, що це добре працює на Chrome, Firefox та IE Edge, якщо ви використовуєте if(!e.relatedTarget && !e.toElement)замість умови фактичну відповідь. Він виявляє, як миша покидає тіло документа.
Haijerome

Не майте події на document.body, тому що панель прокрутки Windows може зменшити її та запустити прокрутку. І чому у вас є "mouseout", який спрацьовує з усіх пухирчастих елементів, коли ви можете мати "mouseleave"? 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";   
    }

}

працює в хромі, фаєрфоксі, опері. 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


Ви перевірили, наскільки добре це працює разом із елементами на сторінці? Я думаю, що елементи, які мають власні події "перемикання / виведення", можуть потенційно скасувати барботаж і порушити цю функціональність.
Ден Герберт

1
Оззі, Ден намагається пояснити, що елемент, який зупиняє розповсюдження подій, не дозволить події дійти до документа / вікна, тим самим зробивши ваше рішення неефективним.
Джеймс

Я щойно перевірив його з іншими елементами з власними подіями 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');
});

Проблема з мишанням та виведенням миші полягає в тому, що якщо ви переходите / вимикаєте html до дочірнього елемента, це призведе до початку події. Функція, яку я дав , не відключається під час спілкування з дочірнім елементом. Він відключається лише тоді, коли ви виходите з миші у вікно

лише для того, щоб ви знали, що ви можете це зробити, коли користувач мишиться у вікні:

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

2
Під "Я не вірю, що JavaScript має еквівалентну функцію", ви маєте на увазі, ви не знаєте, що jQuery - це бібліотека функцій javascript і що jQuery написаний "за" і "для" javascript?
Мілче Патерн

2
@MilchePatern Я написав цю відповідь майже два роки тому. Тоді я був більше необізнаним і не усвідомлював факту, що все, що робиться в jQuery, можна зробити в чистому JavaScript. Я
оновлю

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

Тут ви бачите підтримку браузера

Це було досить коротко, я думав

Але проблема як і раніше залишається, оскільки "миші" викликають усі елементи документа .

Щоб цього не сталося, використовуйте миші (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, тому що панель прокрутки Windows може скоротити тіло і загорітися, коли вказівник миші перестане смугу прокрутки, коли ви хочете прокрутити, але не бажаєте запускати події миші. Встановіть його documentзамість цього, як у прикладі.


1

Можливо, якщо ви постійно слухаєте OnMouseOver у тезі body, тоді зворотний виклик, коли подія не відбувається, але, як заявляє Зак, це може бути дуже некрасиво, оскільки не всі браузери поводяться з подіями однаково, є навіть деякі ймовірність того, що ви втратите MouseOver, навіть перебуваючи над дівом на одній сторінці.


Це не відповідь

1

Можливо, це допоможе дехто з тих, хто приїде сюди пізніше. window.onblurі document.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 - це тоді, коли сам елемент втрачає фокус .. просто згадати.
Мілче Патерн

Розумне використання window.onblurтакож. +1
Програми

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

Дивіться 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

Я цього не перевіряв, але мій інстинкт був би зробити виклик функції OnMouseOut на тезі body.


-2

Це буде працювати в хромі,

$(document).bind('dragleave', function (e) {
    if (e.originalEvent.clientX == 0){
        alert("left window");
    }
});
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.