2017-01-13 70 views
9

Znalazłem bardzo dziwne zachowanie, którego nie potrafię wyjaśnić. Chcesz wykonać następujące czynności:mouseover czasami strzela zamiast touchstart - dlaczego?

Procedura obsługi musi reagować na touchstartlubmouseover przypadku, w zależności od rodzaju urządzenia wejściowego. Zauważ, że chcę obsługiwać urządzenia hybrydowe (z myszą i ekranem dotykowym) i nie mogę polegać na zdarzeniach wskaźnika.

Teraz konfiguruję zarówno zdarzenia touchstart, jak i mouseover. I w większości przypadków działa dobrze. Użyj także preventDefault, aby zabronić symulowanych zdarzeń "myszy" wystrzeliwanych po zdarzeniach dotyku. Ale to, co jest całkowicie mylące dla mnie jest to, że czasamijest wciąż występujące mouseover wydarzenie, a jeśli usunąć preventDefault, to nawet wydaje się, że mouseover jest wypalanie zamiast z touchstart. Dlaczego, och, dlaczego tak się dzieje?

Co więcej, jest on odtwarzalny zarówno na urządzeniach z systemem Android, jak i iOS! Choć wydaje się łatwiej wyzwalany przez Androida (używając Chrome).

Przygotowałem małą próbkę, abyś mógł spróbować sam. Zauważ, że to zachowanie wydaje się być uruchamiane tylko po dotknięciu gdzieś na granicy między czerwonym DIV (który ma zdarzenia) a tłem. Po prostu stukanie w centrum działa w 100%. Możesz potrzebować więcej lub mniej prób, dopóki to się nie stanie.

Każda pomoc bardzo doceniona!

<!DOCTYPE html> 
 
<html> 
 

 
<head> 
 
    <title>Touchtest</title> 
 
    <style> 
 
    body { 
 
     background: #222; 
 
     color: white; 
 
     position: relative; 
 
     font-size: .9em; 
 
     font-family: Arial, Helvetica, sans-serif; 
 
    } 
 
    #test { 
 
     position: fixed; 
 
     top: 100px; 
 
     right: 100px; 
 
     bottom: 100px; 
 
     left: 100px; 
 
     background: red; 
 
    } 
 
    </style> 
 
</head> 
 

 
<body> 
 
    <div id="test"></div> 
 
    <script type="text/javascript"> 
 
    function testEvent(event) { 
 
     console.log("testEvent", event); 
 
     if (event.type === "mouseover") { 
 
     alert("MOUSEOVER DETECTED"); 
 
     } 
 
     event.preventDefault(); 
 
    } 
 

 
    var ele = document.getElementById("test"); 
 
    ele.addEventListener("touchstart", testEvent); 
 
    ele.addEventListener("mouseover", testEvent); 
 
    </script> 
 
</body> 
 

 
</html>

+0

Jeśli spojrzysz na współrzędne zdarzeń mousedown, zobaczysz, że po kliknięciu krawędzi (tuż na zewnątrz) w trybie mobilnym za pomocą Chrome współrzędne nie są poprawne. –

+0

Hej, nie mogę odtworzyć twojego błędu w chrome, https://jsfiddle.net/xvtgc36r/1/ –

+0

Hmm, twój kod nieco się różni. Upewnij się również, że testujesz na urządzeniu dotykowym. –

Odpowiedz

2

Opowiedziałem trochę o twoim przykładzie i wygląda na to, że jest to błąd w Chrome. Nie mogłem go odtworzyć w Firefoksie. można odtworzyć go w narzędziach deweloperskich Chrome na pulpicie i rzeczywiście znalazłem sposób, aby odtworzyć go w 100% przypadków:

  • narzędzi open dev i przełączyć do trybu urządzenia
  • miejsce kręgu kursor na krawędzi czerwonego prostokąta tak, że środek kursora jest poza czerwonym prostokącie chrome dev tool cursor przepraszam za jakość obrazu, nie mogę uchwycić to kursor o zrzucie
  • kliknięcie
  • go do pracy następnym razem, musisz najpierw kliknąć na czarnym backgro und away from red rectangle

Wygląda na to, że dzieje się tak, gdy środek dotyku znajduje się poza prostokątem, ale promień dotyku zachodzi na prostokąt. To powiedziawszy, nie jestem pewien, co możesz tutaj zrobić, z wyjątkiem raportu o błędzie

+0

Tak, dokładnie to zaobserwowałem. Na początku myślałem także o błędzie. Ale czekaj ... spróbuj ponownie w systemie iOS, a zachowanie jest dokładnie to samo. Dlatego jestem tak zdezorientowany. Czy może to być bardzo stary błąd, odwołując się do czasów, gdy Chrome i Safari udostępniały ten sam kod (aka Webkit)? –

+0

Nie jestem pewien, ile dziś współdzielą kod Webkit i Blink, ale jeden z nich jest widelcem drugiego, mogą mieć tę samą logikę, która wyzwala zdarzenia dotykowe. Ale tak czy inaczej, to zachowanie nie wydaje się być czymś, co implementuje mi się celowo, wydaje się, że jest to pomijany efekt uboczny emulacji zdarzenia myszy podczas korzystania z urządzeń dotykowych lub rzeczywistego błędu. Tak czy inaczej prawdopodobnie powinieneś zgłosić ten problem zespołom przeglądarki Chrome i iOS, może to dać ci jaśniejszą odpowiedź :-) – jetpackpony

+0

Zgaduję, że masz rację. Dziękuję za sprawdzenie tego i myślę, że zasłużyłeś na swoją nagrodę;) –

2

Zdarzenia myszy (przesunięć myszy, mouseOut, mouseDown mouseUp, mousemove, etc.) są przypisane do urządzenia wejściowego myszy.

Zdarzenie javascript najechania kursorem myszy zostanie przetłumaczone na zdarzenia dotykowe touchenter. To wydarzenie jest częścią szkicu W3C (obecnie tylko obsługa Firefoxa), więc jeśli chcesz z niego korzystać, musisz zaimplementować swoją funkcję onmouseover za pomocą zdarzenia touchmove i sprawdzić współrzędne i sprawdzić, czy pokrywają się ze współrzędnymi twojego html element.

Myślę, że to ci pomaga.

+0

Przykro mi to mówić, ale nie przeczytałeś dokładnie mojego pytania, a dodatkowo twoja odpowiedź jest po prostu błędna. Przede wszystkim zdarzenia myszy NIE są specyficzne dla urządzenia wejściowego myszy! Zdarzenia myszy są generowane dobrze podczas korzystania z dotyku, tak zwane "zdarzenia syntetyczne". Podczas korzystania z dotyku generowane są BOTE zdarzenia dotykowe i myszy, przy czym zdarzenia myszy zwykle są wyzwalane po wydarzeniach dotyku. Moje pytanie w rzeczywistości dotyczy tego, czy klient uruchamia zdarzenie "mouseover" TYLKO podczas używania dotyku (tj. Bez uprzednich zdarzeń dotykowych) w pewnych okolicznościach (co nie powinno się zdarzyć i sprawia, że ​​jest o wiele trudniej). –