Tworzę aplikację internetową (nie witrynę internetową ze stronami z interesującym tekstem) z bardzo innym interfejsem dotykowym (palec chowa ekran po kliknięciu) i myszy (w dużej mierze opiera się na podglądzie po najechaniu kursorem). Jak mogę wykryć, że mój użytkownik nie ma myszy, aby pokazać mu właściwy interfejs? Planuję zostawić przełącznik dla osób z myszą i dotykiem (jak niektóre notebooki).
Możliwość obsługi zdarzenia dotykowego w przeglądarce nie oznacza w rzeczywistości, że użytkownik korzysta z urządzenia dotykowego (na przykład Modernizr go nie przerywa). Kod, który poprawnie odpowiada na pytanie, powinien zwracać fałsz, jeśli urządzenie jest wyposażone w mysz, w przeciwnym razie prawda. W przypadku urządzeń z myszą i dotykiem powinna zwracać wartość false (nie tylko dotyk)
Na marginesie, mój interfejs dotykowy może być również odpowiedni dla urządzeń obsługujących tylko klawiaturę, więc raczej chodzi o brak myszy, który chcę wykryć.
Aby wyjaśnić tę potrzebę, oto API, które chcę zaimplementować:
// Level 1
// The current answers provide a way to do that.
hasTouch();
// Returns true if a mouse is expected.
// Note: as explained by the OP, this is not !hasTouch()
// I don't think we have this in the answers already, that why I offer a bounty
hasMouse();
// Level 2 (I don't think it's possible, but maybe I'm wrong, so why not asking)
// callback is called when the result of "hasTouch()" changes.
listenHasTouchChanges(callback);
// callback is called when the result of "hasMouse()" changes.
listenHasMouseChanges(callback);
źródło
Odpowiedzi:
Główny problem polega na tym, że masz następujące różne klasy urządzeń / przypadków użycia:
Co gorsza, można przejść z niektórych z tych klas do innych (podłącza się mysz, łączy się z klawiaturą), lub użytkownik może WYGLĄDAĆ na zwykłego laptopa, dopóki nie wyciągnie ręki i nie dotknie ekranu.
Masz rację, zakładając, że obecność konstruktorów zdarzeń w przeglądarce nie jest dobrym sposobem na robienie postępów (i jest nieco niespójna). Ponadto, jeśli nie śledzisz bardzo konkretnego zdarzenia lub tylko próbujesz wykluczyć kilka powyższych klas, użycie samych zdarzeń nie jest pełnym dowodem.
Załóżmy na przykład, że odkryłeś, że użytkownik wyemitował prawdziwe ruchy myszy (a nie fałszywe ze zdarzeń dotykowych, zobacz http://www.html5rocks.com/en/mobile/touchandmouse/ ).
Więc co?
Włączasz style najechania? Dodajesz więcej przycisków?
Tak czy inaczej, wydłużasz czas potrzebny na szkło, ponieważ musisz poczekać na uruchomienie zdarzenia.
Ale co się stanie, gdy twój szlachetny użytkownik zdecyduje się odłączyć mysz i przejść do pełnego kontaktu ... czy czekasz, aż dotknie twojego teraz zapchanego interfejsu, a następnie zmień go zaraz po tym, jak spróbuje zlokalizować twój teraz zatłoczony interfejs użytkownika?
W formie punktorów, cytując stucox na https://github.com/Modernizr/Modernizr/issues/869#issuecomment-15264101
Na marginesie: przeglądarka WIE, kiedy użytkownik podłącza mysz / klawiaturę, ale nie wystawia jej na działanie JavaScript ... dang!
Powinno to doprowadzić do następujących sytuacji:
Jednak idea stopniowego ulepszania ma tutaj zastosowanie. Zbuduj środowisko, które działa płynnie bez względu na kontekst użytkownika. Następnie przyjmij założenia na podstawie funkcji przeglądarki / zapytań o media, aby dodać funkcjonalność, która będzie względna w założonym kontekście. Obecność myszy to tylko jeden z wielu sposobów, w jakie różni użytkownicy różnych urządzeń korzystają z Twojej witryny. Stwórz coś wartościowego w swoim jądrze i nie przejmuj się zbytnio tym, jak ludzie klikają przyciski.
źródło
:hover
Elementów i tym podobnych), gdy użytkownik przełącza się z myszy na dotyk. Wydaje się mało prawdopodobne, że użytkownik aktualnie używa myszy + dotyku w tym samym czasie (mam na myśli comoonn to tak, jakby mieć 2 myszy podłączone do tego samego komputera hahaha)Co powiesz na nasłuchiwanie zdarzenia mousemove w dokumencie. Następnie, dopóki nie usłyszysz tego zdarzenia, zakładasz, że urządzenie jest tylko dotykowe lub klawiaturowe.
(Gdzie
listen
iunlisten
delegujaddEventListener
lubattachEvent
odpowiednio.)Miejmy nadzieję, że nie doprowadziłoby to do zbytniego wizualnego szarpnięcia, byłoby do niczego, gdybyś potrzebował ogromnych zmian układów opartych na trybie ...
źródło
Od 2018 roku istnieje dobry i niezawodny sposób wykrywania, czy przeglądarka ma mysz (lub podobne urządzenie wejściowe): funkcje interakcji z mediami CSS4, które są teraz obsługiwane przez prawie każdą nowoczesną przeglądarkę (z wyjątkiem IE 11 i specjalnych przeglądarek mobilnych).
W3C:
Zobacz następujące opcje:
Zapytania o media mogą być również używane w JS:
Związane z:
Dokumentacja W3: https://www.w3.org/TR/mediaqueries-4/#mf-interaction
Obsługa przeglądarek: https://caniuse.com/#search=media%20features
Podobny problem: Wykryj, czy urządzenie klienckie obsługuje stany: hover i: focus
źródło
Odpowiedź @ Wyatta jest świetna i daje nam wiele do przemyślenia.
W moim przypadku zdecydowałem się nasłuchiwać pierwszej interakcji, a dopiero potem ustawić zachowanie. Więc nawet jeśli użytkownik ma mysz, będę traktować jako urządzenie dotykowe, jeśli pierwsza interakcja była dotykiem.
Biorąc pod uwagę podaną kolejność przetwarzania zdarzeń :
Możemy założyć, że jeśli zdarzenie myszy zostanie wyzwolone przed dotykiem, jest to prawdziwe zdarzenie myszy, a nie emulowane. Przykład (przy użyciu jQuery):
To zadziałało dla mnie
źródło
Można tylko wykryć, czy przeglądarka obsługuje dotyk . Nie ma sposobu, aby dowiedzieć się, czy faktycznie ma podłączony ekran dotykowy lub mysz.
Można jednak ustalić priorytety użytkowania, nasłuchując zdarzenia dotyku zamiast zdarzenia myszy, jeśli wykryta zostanie funkcja dotyku.
Aby wykryć obsługę dotykową w różnych przeglądarkach:
Następnie można to wykorzystać do sprawdzenia:
lub wybrać, którego zdarzenia słuchać, albo:
lub użyj oddzielnych podejść dla dotyku i niedotyku:
W przypadku myszy można tylko wykryć, czy mysz jest używana, a nie, czy istnieje, czy nie. Można ustawić globalną flagę, aby wskazać, że mysz została wykryta przez użycie (podobnie do istniejącej odpowiedzi, ale nieco uproszczonej):
(nie można uwzględniać
mouseup
ani,mousedown
ponieważ zdarzenie to można również wywołać dotykiem)Przeglądarki ograniczają dostęp do niskopoziomowych interfejsów API systemu, które są potrzebne do wykrywania funkcji, takich jak możliwości sprzętowe systemu, w którym są używane.
Istnieje możliwość napisania wtyczki / rozszerzenia, aby uzyskać do nich dostęp, ale za pomocą JavaScript i DOM takie wykrywanie jest ograniczone do tego celu i należałoby napisać wtyczkę specyficzną dla różnych platform OS.
Podsumowując: takie wykrycie można oszacować jedynie na podstawie „dobrego przypuszczenia”.
źródło
Kiedy Media Queries Level 4 będą dostępne w przeglądarkach, będziemy mogli używać zapytań „wskaźnik” i „hover” do wykrywania urządzeń za pomocą myszy.
Jeśli naprawdę chcemy przekazać te informacje do Javascript, możemy użyć zapytania CSS, aby ustawić określone style zgodnie z typem urządzenia, a następnie użyć
getComputedStyle
w Javascript do odczytania tego stylu i wyprowadzenia z niego oryginalnego typu urządzenia.Ale mysz można podłączyć lub odłączyć w dowolnym momencie, a użytkownik może chcieć przełączać się między dotykiem a myszą. Dlatego może być konieczne wykrycie tej zmiany i zaproponowanie zmiany interfejsu lub zrobienie tego automatycznie.
źródło
any-pointer
iany-hover
pozwoli Ci zbadać wszystkie odpowiednie możliwości urządzenia. Miło jest zobaczyć, jak możemy rozwiązać ten problem w przyszłości! :)Ponieważ i tak planujesz zaoferować sposób przełączania się między interfejsami, czy byłoby możliwe po prostu poprosić użytkownika o kliknięcie łącza lub przycisku w celu „wprowadzenia” prawidłowej wersji aplikacji? Wtedy można było zapamiętać ich preferencje co do przyszłych wizyt. To nie jest high-tech, ale jest w 100% niezawodny :-)
źródło
@SamuelRossille Żadne przeglądarki, o których jestem świadomy, nie ujawniają niestety istnienia (lub braku) myszy.
Mając to na uwadze, musimy po prostu spróbować i zrobić wszystko, co w naszej mocy, z naszą istniejącą opcją ... wydarzeniami. Wiem, że to nie jest dokładnie to, czego szukasz ... zgodził się, że obecnie jest daleki od ideału.
Możemy zrobić wszystko, co w naszej mocy, aby dowiedzieć się, czy użytkownik w danym momencie używa myszy, czy dotyku. Oto szybki i brudny przykład użycia jQuery & Knockout:
Możesz teraz powiązać / zasubskrybować usingMouse () i usingTouch () i / lub stylizować swój interfejs za pomocą klasy body.mouse . Interfejs będzie się przełączał w tę i z powrotem, gdy tylko zostanie wykryty kursor myszy i po uruchomieniu Touchstart.
Mamy nadzieję, że wkrótce będziemy mieli lepsze opcje od dostawców przeglądarek.
źródło
Tera-WURFL może poinformować Cię o możliwościach urządzenia odwiedzającego Twoją witrynę , porównując sygnaturę przeglądarki z jej bazą danych. Zobacz, jest za darmo!
źródło
Dlaczego po prostu nie wykryjesz, czy ma zdolność wyczuwania dotyku i / lub reagowania na ruchy myszy?
źródło
has_touch = 'ontouchstart' in window
wystarczy i tak dalej.U mnie to zadziałało w podobnej sytuacji. Zasadniczo załóżmy, że użytkownik nie ma myszy, dopóki nie zobaczysz krótkiej serii następujących po sobie ruchów myszą, bez przerywanych naciśnięć myszy lub przesunięć myszy. Niezbyt eleganckie, ale działa.
źródło
Spójrz na modenizr, jedną z jego funkcji jest dotyk
http://modernizr.com/docs/#features-misc
Chociaż nie testowałem w pełni, wydaje się, że działa bardzo dobrze
Jest to również link ze strony modernizr http://www.html5rocks.com/en/mobile/touchandmouse/
źródło
Jak zauważyli inni, ostateczne wykrycie, czy mają mysz, jest zawodne. W zależności od urządzenia można to łatwo zmienić. Zdecydowanie jest to coś, czego nie można niezawodnie zrobić z logiczną prawdą lub fałszem, przynajmniej w skali dokumentu.
Wydarzenia związane z dotykiem i myszy są ekskluzywne. Może to trochę pomóc w podejmowaniu różnych działań. Problem polega na tym, że zdarzenia dotyku są bliżej zdarzeń myszy w górę / w dół / ruchu, a także wyzwalają zdarzenie kliknięcia.
Z twojego pytania mówisz, że chcesz mieć najechanie na podgląd. Poza tym nie znam żadnych innych szczegółów dotyczących twojego interfejsu. Jestem zakładając, że przy braku myszy chcesz kranu do podglądu, natomiast kliknięcie wykonuje inną czynność ze względu na podgląd hover.
Jeśli tak jest, możesz przyjąć nieco leniwe podejście do wykrywania:
Zdarzenie onclick zawsze będzie poprzedzone zdarzeniem onmouseover za pomocą myszy. Zwróć więc uwagę, że mysz znajduje się nad elementem, który został kliknięty.
Możesz to zrobić za pomocą zdarzenia onmousemove obejmującego cały dokument. Możesz użyć
event.target
do zarejestrowania elementu, na którym znajduje się mysz. Następnie w zdarzeniach onclick możesz sprawdzić, czy mysz faktycznie znajduje się nad klikanym elementem (lub elementem podrzędnym elementu).Stamtąd możesz zdecydować, czy chcesz polegać na zdarzeniu kliknięcia dla obu i wykonać akcję A lub B w zależności od wyniku. Akcja B mogłaby być niczym, gdyby niektóre urządzenia dotykowe nie emitowały zdarzenia kliknięcia (zamiast tego musiałbyś polegać na zdarzeniach ontouch *).
źródło
Nie sądzę, aby można było zidentyfikować urządzenie dotykowe (oczywiście zgodnie z moją wiedzą). Głównym problemem jest to, że wszystkie zdarzenia myszy i klawiatury są również uruchamiane przez urządzenia dotykowe. Zobacz poniższy przykład, oba alerty zwracają wartość true dla urządzeń dotykowych.
źródło
true
do'onmousedown' in window
Moim zdaniem najlepszym pomysłem jest
mousemove
słuchacz (obecnie najlepsza odpowiedź). Uważam, że tę metodę należy nieco poprawić. Prawdą jest, że przeglądarki dotykowe naśladują nawet zdarzenie mousemove, jak widać w tej dyskusji na temat iOS , więc powinniśmy być trochę ostrożni.Ma sens, że przeglądarki dotykowe będą emulować to zdarzenie tylko wtedy, gdy użytkownik dotknie ekranu (palec użytkownika jest opuszczony). Oznacza to, że powinniśmy dodać test podczas naszej obsługi ruchu myszy, aby zobaczyć, który przycisk myszy jest wciśnięty (jeśli w ogóle) podczas zdarzenia. Jeśli żaden przycisk myszy nie jest wciśnięty, możemy bezpiecznie założyć, że obecna jest prawdziwa mysz. Jeśli przycisk myszy nie działa, test nie daje jednoznacznych wyników.
Jak więc miałoby to zostać wdrożone? To pytanie pokazuje, że najbardziej niezawodną metodą sprawdzenia, który przycisk myszy jest wciśnięty podczas ruchu myszy, jest faktycznie nasłuchiwanie 3 zdarzeń na poziomie dokumentu: przesunięcie myszy, przesunięcie myszy i przesunięcie myszy. W górę iw dół ustawia tylko globalną flagę logiczną. Ruch wykona test. Jeśli masz ruch, a wartość logiczna jest fałszywa, możemy założyć, że obecna jest mysz. Zobacz pytanie, aby uzyskać dokładne przykłady kodu.
Ostatnia uwaga. Ten test nie jest idealny, ponieważ nie można go wykonać w czasie ładowania. Dlatego użyłbym metody progresywnego ulepszania, jak sugerowano wcześniej. Domyślnie pokazuje wersję, która nie obsługuje interfejsu dymka specyficznego dla myszy. Jeśli mysz zostanie wykryta, włącz ten tryb w środowisku wykonawczym za pomocą JS. Powinno to wyglądać tak płynnie, jak to tylko możliwe dla użytkownika.
W celu obsługi zmian w konfiguracji użytkownika (tj. Mysz została odłączona), możesz okresowo przeprowadzać testy ponownie. Chociaż uważam, że w tym przypadku lepiej będzie po prostu powiadomić użytkownika o 2 trybach i pozwolić użytkownikom ręcznie przełączać się między nimi (podobnie jak wybór mobilny / komputer stacjonarny, który zawsze można odwrócić).
źródło
Przeprowadziłem kilka testów na różnych komputerach PC, Linuksie, iPhonie, telefonach z Androidem i kartach. Dziwne, że nie ma łatwego, kuloodpornego rozwiązania. Problem pojawia się, gdy niektóre urządzenia, które mają dotyk i nie mają myszy, nadal prezentują zdarzenia dotyku i myszy w aplikacji. Ponieważ chcesz obsługiwać instancje tylko myszą i tylko dotykowe, chcesz przetwarzać oba, ale to powoduje podwójne wystąpienie interakcji użytkownika. Jeśli może wiedzieć, że na urządzeniu nie ma myszy, może wiedzieć, że należy ignorować fałszywe / wstawione zdarzenia myszy. Próbowano ustawić flagę w przypadku napotkania MouseMove, ale niektóre przeglądarki wyświetlają fałszywe MouseMove, a także MouseUp i MouseDown. Próbowałem sprawdzić sygnatury czasowe, ale doszedłem do wniosku, że jest to zbyt ryzykowne. Podsumowując: znalazłem przeglądarki, które tworzyły fałszywe zdarzenia myszy, zawsze wstawiały pojedynczy MouseMove tuż przed wstawionym MouseDown. W 99,99% moich przypadków podczas pracy w systemie z prawdziwą myszą występuje wiele następujących po sobie zdarzeń MouseMove - co najmniej dwa. Więc śledź, czy system napotyka dwa kolejne zdarzenia MouseMove i deklaruj, że nie ma myszy, jeśli ten warunek nigdy nie zostanie spełniony. To prawdopodobnie zbyt proste, ale działa na wszystkich moich konfiguracjach testowych. Myślę, że będę się tego trzymać, dopóki nie znajdę lepszego rozwiązania. - Jim W.
źródło
Proste rozwiązanie w jQuery do wykrywania użycia myszy, które rozwiązuje problem, w którym urządzenia mobilne również wyzwalają zdarzenie „mousemove”. Po prostu dodaj nasłuchiwanie Touchstart, aby usunąć nasłuchiwanie myszy, aby nie było uruchamiane przy dotknięciu.
Oczywiście urządzenie nadal może być dotykowe i myszką, ale powyższe zagwarantuje, że została użyta prawdziwa mysz.
źródło
Właśnie znalazłem rozwiązanie, które moim zdaniem jest dość eleganckie.
źródło
Napotkałem ten sam problem, w którym pojedynczy dotyk był również rejestrowany jako kliknięcie. Po przeczytaniu komentarzy do najczęściej głosowanych odpowiedzi znalazłem własne rozwiązanie:
Jedynym problemem, jaki znalazłem, jest to, że musisz mieć możliwość przewijania, aby poprawnie wykryć zdarzenie dotykowe. pojedyncza zakładka (dotyk) może powodować problemy.
źródło
Spędziłem godziny na rozwiązywaniu tego problemu w mojej aplikacji Phonegap i wymyśliłem ten hack. Generuje ostrzeżenie konsoli, jeśli wyzwolone zdarzenie jest zdarzeniem „pasywnym”, co oznacza, że nie uruchamia żadnej zmiany, ale działa! Byłbym zainteresowany wszelkimi pomysłami na ulepszenie lub lepszą metodę. Ale to skutecznie pozwala mi uniwersalnie używać $ .touch ().
źródło
główny problem, jaki tutaj widzę, to fakt, że większość urządzeń dotykowych uruchamia zdarzenie myszy wraz z odpowiadającym mu zdarzeniem dotykowym (touchstart -> ruch myszy, ruch myszy -> ruch myszy, itp.). W przypadku klawiatury tylko i wreszcie dla nowoczesnych mają ogólną przeglądarkę, więc nie można nawet wykryć obecności klasy MouseEvent.
Mniej bolesnym rozwiązaniem byłoby, moim zdaniem, wyświetlenie menu przy uruchomieniu (z zarządzaniem `` alt '' dla użytkowników tylko z klawiaturą) i być może przechowywanie wyboru w localStorage / cookies / serveride lub pozostawienie tego samego wyboru w następnym gdy gość przyjdzie.
źródło
Zdecydowanie odradzam takie podejście. Weź pod uwagę ekrany dotykowe, urządzenia wielkości komputera stacjonarnego, a będziesz musiał rozwiązać inny zestaw problemów.
Spraw, aby aplikacja działała bez myszy (tj. Bez podglądu po najechaniu myszą).
źródło
Chciałbym polecić skrypt, który mi pomógł:
Przeczytałem i wypróbowałem wszystko, co zasugerowałem, bez wystarczających rezultatów.
Następnie zbadałem trochę więcej i znalazłem ten kod - device.js
Używam tego w witrynie mojego klienta, aby wykryć obecność myszy:
(
<html>
powinien miećdesktop
klasę) i wydaje się całkiem niezły, a dlatouch
wsparcia po prostu regularnie sprawdzam'ontouchend' in document
i używam informacji z obu wykryć, aby założyć określoną rzecz, której potrzebuję.źródło
Generalnie lepszym pomysłem jest wykrycie, czy funkcja przesuwania myszy jest obsługiwana, niż wykrywanie typu systemu operacyjnego / przeglądarki. Możesz to zrobić, wykonując następujące czynności:
Upewnij się, że nie wykonujesz następujących czynności:
Ten ostatni faktycznie wywołałby metodę, zamiast sprawdzać jej istnienie.
Możesz przeczytać więcej tutaj: http://www.quirksmode.org/js/support.html
źródło