Estoy desarrollando una aplicación web (no un sitio web con páginas de texto interesante) con una interfaz táctil muy diferente (su dedo oculta la pantalla cuando hace clic) y el mouse (depende en gran medida de la vista previa de desplazamiento). ¿Cómo puedo detectar que mi usuario no tiene mouse para presentarle la interfaz correcta? Tengo la intención de dejar un interruptor para las personas con el mouse y el tacto (como algunos portátiles).
La capacidad de evento táctil en el navegador no significa que el usuario esté usando un dispositivo táctil (por ejemplo, Modernizr no lo corta). El código que responde correctamente a la pregunta debería devolver falso si el dispositivo tiene un mouse, de lo contrario, verdadero. Para dispositivos con mouse y touch, debería devolver false (no solo touch)
Como nota al margen, mi interfaz táctil también puede ser adecuada para dispositivos con solo teclado, por lo que es más la falta de mouse que estoy buscando detectar.
Para aclarar la necesidad, aquí está la API que estoy buscando implementar:
// 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);
fuente
Respuestas:
El principal problema es que tiene las siguientes clases diferentes de dispositivos / casos de uso:
Lo que es peor, es que uno puede hacer la transición de algunas de estas clases a otras (conecta un mouse, se conecta al teclado), o puede aparecer un usuario en una computadora portátil normal hasta que alcancen y toquen la pantalla.
Tiene razón al suponer que la presencia de constructores de eventos en el navegador no es una buena manera de avanzar (y es algo inconsistente). Además, a menos que esté rastreando un evento muy específico o solo esté tratando de descartar algunas clases anteriores, el uso de eventos en sí no es una prueba completa.
Por ejemplo, supongamos que descubrió que un usuario ha emitido un movimiento real del mouse (no el falso de los eventos táctiles, consulte http://www.html5rocks.com/en/mobile/touchandmouse/ ).
¿Y que?
¿Habilitas los estilos de desplazamiento? ¿Agregas más botones?
De cualquier manera, está aumentando el tiempo de cristal porque tiene que esperar a que se active un evento.
Pero entonces, ¿qué sucede cuando su noble usuario decide que quiere desconectar su mouse e ir a tocarlo por completo?
En forma de viñeta, citando stucox en https://github.com/Modernizr/Modernizr/issues/869#issuecomment-15264101
Un aparte: el navegador SÍ sabe cuándo un usuario conecta un mouse / se conecta a un teclado, pero no lo expone a JavaScript ... ¡dang!
Esto debería llevarlo a lo siguiente:
Sin embargo, la idea de mejora progresiva se aplica bastante bien aquí. Cree una experiencia que funcione sin problemas sin importar el contexto del usuario. Luego haga suposiciones basadas en las características del navegador / consultas de medios para agregar funcionalidades que serán relativas en el contexto asumido. La presencia de un mouse es solo una de las múltiples formas en que diferentes usuarios en diferentes dispositivos experimentan su sitio web. Cree algo con mérito en su núcleo y no se preocupe demasiado por cómo la gente hace clic en los botones.
fuente
:hover
elementos y cosas así) cuando el usuario cambia de mouse a táctil. Parece poco probable que el usuario esté usando el mouse + touch exactamente al mismo tiempo (quiero decir, como es como tener 2 ratones conectados a la misma computadora jajaja)¿Qué tal escuchar un evento de mousemove en el documento? Luego, hasta que escuche ese evento, asuma que el dispositivo es solo táctil o de teclado.
(Donde
listen
yunlisten
delegaraddEventListener
aoattachEvent
según corresponda)Esperemos que esto no conduzca a demasiado jank visual, sería una mierda si necesita rediseños masivos basados en el modo ...
fuente
A partir de 2018, hay una forma buena y confiable de detectar si un navegador tiene un mouse (o dispositivo de entrada similar): características de interacción de medios CSS4 que ahora son compatibles con casi cualquier navegador moderno (excepto IE 11 y navegadores móviles especiales).
W3C:
Ver las siguientes opciones:
Las consultas de medios también se pueden usar en JS:
Relacionado:
Documentación de W3: https://www.w3.org/TR/mediaqueries-4/#mf-interaction
Soporte de navegador: https://caniuse.com/#search=media%20features
Problema similar: detectar si un dispositivo cliente admite: hover y: estados de enfoque
fuente
La respuesta de @ Wyatt es excelente y nos da mucho en qué pensar.
En mi caso, elegí escuchar la primera interacción, para luego establecer un comportamiento. Entonces, incluso si el usuario tiene un mouse, trataré como dispositivo táctil si la primera interacción fue táctil.
Teniendo en cuenta el orden dado en el que se procesan los eventos :
Podemos suponer que si el evento del mouse se dispara antes del toque, es un evento real del mouse, no uno emulado. Ejemplo (usando jQuery):
Eso funciono para mi
fuente
Solo es posible detectar si un navegador tiene capacidad táctil . No hay forma de saber si realmente tiene una pantalla táctil o un mouse conectado.
Sin embargo, se puede priorizar el uso al escuchar el evento táctil en lugar del evento del mouse si se detecta la capacidad táctil.
Para detectar la capacidad táctil entre navegadores:
Entonces uno puede usar esto para verificar:
o para elegir qué evento escuchar, ya sea:
o use enfoques separados para tocar versus no tocar:
Para el mouse, uno solo puede detectar si se está usando el mouse, no si existe o no. Se puede configurar un indicador global para indicar que el mouse fue detectado por el uso (similar a una respuesta existente, pero simplificado un poco):
(no se puede incluir
mouseup
omousedown
ya que estos eventos también se pueden activar al tocarlos)Los navegadores restringen el acceso a las API de sistema de bajo nivel que se necesitan para poder detectar características como las capacidades de hardware del sistema en el que se está utilizando.
Existe la posibilidad de quizás escribir un complemento / extensión para acceder a estos, pero a través de JavaScript y DOM, dicha detección es limitada para este propósito y uno tendría que escribir un complemento específico para las diversas plataformas del sistema operativo.
En conclusión: tal detección solo puede estimarse mediante una "buena suposición".
fuente
Cuando Media Queries Level 4 está disponible en los navegadores, podremos usar las consultas "puntero" y "hover" para detectar dispositivos con un mouse.
Si realmente queremos comunicar esa información a Javascript, podríamos usar una consulta CSS para establecer estilos específicos de acuerdo con el tipo de dispositivo, y luego usar
getComputedStyle
en Javascript para leer ese estilo y derivar el tipo de dispositivo original de él.Pero un mouse se puede conectar o desconectar en cualquier momento, y el usuario puede querer cambiar entre el tacto y el mouse. Por lo tanto, es posible que necesitemos detectar este cambio y ofrecer cambiar la interfaz o hacerlo automáticamente.
fuente
any-pointer
yany-hover
le permitirá investigar todas las capacidades aplicables del dispositivo. ¡Es bueno echar un vistazo a cómo podríamos resolver este problema en el futuro! :)Como planea ofrecer una forma de cambiar entre las interfaces de todos modos, ¿sería factible simplemente pedirle al usuario que haga clic en un enlace o un botón para "ingresar" la versión correcta de la aplicación? Entonces podría recordar su preferencia para futuras visitas. No es de alta tecnología, pero es 100% confiable :-)
fuente
@SamuelRossille No hay navegadores que yo sepa que expongan la existencia (o la falta de ella) de un mouse, desafortunadamente.
Entonces, dicho esto, solo tenemos que intentar y hacer lo mejor que podamos con nuestra opción existente ... eventos. Sé que no es exactamente lo que estás buscando ... de acuerdo, actualmente está lejos de ser ideal.
Podemos hacer todo lo posible para determinar si un usuario está usando un mouse o táctil en un momento dado. Aquí hay un ejemplo rápido y sucio con jQuery & Knockout:
Ahora puede enlazar / suscribirse a usingMouse () y usingTouch () y / o diseñar su interfaz con la clase body.mouse . La interfaz cambiará de un lado a otro tan pronto como se detecte un cursor del mouse y al inicio táctil.
Esperemos que pronto tengamos mejores opciones de los proveedores de navegadores.
fuente
Tera-WURFL puede decirle las capacidades del dispositivo que está visitando su sitio comparando la firma del navegador con su base de datos. Dale un vistazo, es gratis!
fuente
¿Por qué no detecta si tiene la capacidad de sentir toques y / o reaccionar a los movimientos del mouse?
fuente
has_touch = 'ontouchstart' in window
será suficiente, y así sucesivamente.Esto funcionó para mí en una situación similar. Básicamente, suponga que el usuario no tiene un mouse hasta que vea una serie corta de movimientos consecutivos del mouse, sin intervenir mousedowns o mouseups. No muy elegante, pero funciona.
fuente
Echa un vistazo a modenizr una de sus características es táctil
http://modernizr.com/docs/#features-misc
Si bien no lo he probado completamente, parece funcionar muy bien
También esto está vinculado desde la página modernizr http://www.html5rocks.com/en/mobile/touchandmouse/
fuente
Como otros han señalado, detectar definitivamente si tienen o no un mouse no es confiable. Esto puede cambiar fácilmente, dependiendo del dispositivo. Definitivamente es algo que no puede hacer de manera confiable con un booleano verdadero o falso, al menos en una escala de documentos.
Los eventos táctiles y los eventos del mouse son exclusivos. Entonces, esto puede ayudar de alguna manera a tomar diferentes acciones. El problema es que los eventos táctiles están más cerca de los eventos arriba / abajo / movimiento del mouse, y también desencadenan un evento de clic.
De tu pregunta, dices que quieres tener un cursor para previsualizar. Más allá de eso, no conozco otros detalles sobre su interfaz. Estoy asumiendo que con la falta de un ratón que desea un grifo de vista previa, mientras que un clic hace una acción diferente a causa de la vista previa de la libración.
Si ese es el caso, puede adoptar un enfoque un tanto vago para la detección:
Un evento onclick siempre estará precedido por un evento onmouseover con un mouse. Por lo tanto, tenga en cuenta que el mouse está encima del elemento en el que se ha hecho clic.
Puede hacer esto con un evento onmousemove en todo el documento. Puede usar
event.target
para registrar en qué elemento reside el mouse. Luego, dentro de sus eventos onclick, puede verificar si el mouse está realmente sobre el elemento en el que se hace clic (o un elemento secundario del elemento).Desde allí, puede elegir confiar en el evento de clic para ambos y tomar una acción A o B según el resultado. La acción B podría no ser nada si algunos dispositivos táctiles no emiten un evento de clic (en su lugar, tendría que confiar en los eventos ontouch *).
fuente
No creo que sea posible identificar dispositivos táctiles (que yo sepa, por supuesto). El problema principal es que todos los eventos de mouse y teclado también se activan con dispositivos táctiles. Vea el siguiente ejemplo, ambas alertas devuelven verdadero para dispositivos táctiles.
fuente
true
para'onmousedown' in window
La mejor idea en mi opinión es el
mousemove
oyente (actualmente la respuesta principal). Creo que este método debe modificarse un poco. Es cierto que los navegadores táctiles emulan incluso el evento mousemove, como puede ver en esta discusión de iOS , por lo que debemos tener un poco de cuidado.Tiene sentido que los navegadores táctiles solo emulen este evento cuando el usuario toca la pantalla (el dedo del usuario está hacia abajo). Esto significa que debemos agregar una prueba durante nuestro controlador de movimiento del mouse para ver qué botón del mouse está presionado (si corresponde) durante el evento. Si no hay ningún botón del mouse presionado, podemos asumir con seguridad que hay un mouse real presente. Si un botón del mouse está presionado, la prueba no es concluyente.
Entonces, ¿cómo se implementaría esto? Esta pregunta muestra que el método más confiable para examinar qué botón del mouse está presionado durante un movimiento del mouse es escuchar realmente 3 eventos en el nivel del documento: mousemove, mousedown y mouseup. Arriba y abajo solo establecerán una bandera booleana global. El movimiento realizará la prueba. Si tiene un movimiento y el valor booleano es falso, podemos suponer que hay un mouse presente. Ver pregunta para ejemplos de código exacto.
Un comentario final ... Esta prueba no es ideal porque no se puede realizar en tiempo de carga. Por lo tanto, usaría un método de mejora progresiva como se sugirió anteriormente. De manera predeterminada, muestra una versión que no admite la interfaz de desplazamiento específico del mouse. Si se descubre un mouse, habilite este modo en tiempo de ejecución utilizando JS. Esto debería parecer lo más sencillo posible para el usuario.
Para admitir cambios en la configuración del usuario (es decir, el mouse se ha desconectado), puede volver a realizar pruebas periódicamente. Aunque creo que será mejor en este caso simplemente notificar al usuario sobre los 2 modos y dejar que los usuarios cambien manualmente entre ellos (al igual que la opción móvil / escritorio que siempre se puede revertir).
fuente
Ejecuté algunas pruebas en varias PC, Linux, iPhone, teléfonos Android y pestañas. Extraño que no haya una solución fácil a prueba de balas. El problema surge cuando algunos que tienen Touch y no mouse todavía presentan eventos Touch y Mouse a la aplicación. Dado que desea admitir instancias solo de mouse y solo de tacto, desea procesar ambas, pero esto provoca una doble aparición de interacciones del usuario. Si puede saber que el mouse no está presente en el dispositivo, puede ignorar los eventos falsos / insertados del mouse. Intenté configurar la marca si se encuentra MouseMove, pero algunos navegadores arrojan MouseMove falso, así como MouseUp y MouseDown. Intenté examinar las marcas de tiempo pero pensé que esto era demasiado arriesgado. En pocas palabras: los navegadores que crearon los eventos falsos del mouse siempre insertaron un solo MouseMove justo antes del MouseDown insertado. En el 99.99% de mis casos, cuando se ejecuta en un sistema que tiene un mouse real, hay varios eventos MouseMove consecutivos, al menos dos. Por lo tanto, realice un seguimiento de si el sistema encuentra dos eventos MouseMove consecutivos y declare que no hay mouse presente si esta condición nunca se cumple. Probablemente sea demasiado simple, pero funciona en todas mis configuraciones de prueba. Creo que me quedaré con eso hasta que encuentre una mejor solución. - Jim W
fuente
Una solución simple en jQuery para detectar el uso del mouse, que resuelve el problema donde los dispositivos móviles también activan el evento 'mousemove'. Simplemente agregue un oyente de inicio táctil para eliminar el oyente del mousemove, para que no se active al tocarlo.
Por supuesto, el dispositivo aún podría ser táctil Y mouse, pero lo anterior garantizará que se usó un mouse real.
fuente
Acabo de encontrar una solución que creo que es bastante elegante.
fuente
Me encontré con el mismo problema, donde un solo toque también se registró como un clic. Después de leer los comentarios de las respuestas más votadas, se me ocurrió mi propia solución:
El único problema que encontré es que debes poder desplazarte para detectar correctamente un evento táctil. una sola pestaña (táctil) puede causar problemas.
fuente
Pasé horas resolviendo este problema para mi aplicación Phonegap y se me ocurrió este truco. Genera una advertencia de consola si el evento desencadenado es un evento "pasivo", lo que significa que no activa ningún cambio, ¡pero funciona! Me interesaría cualquier idea para mejorar o un método mejor. Pero esto efectivamente me permite usar $ .touch () universalmente.
fuente
El principal problema que veo aquí es que la mayoría de los dispositivos táctiles activan un evento del mouse junto con el correspondiente touch touch (inicio táctil -> mousedown, touchmove -> mousemove, etc.). Solo para los teclados, al fin para los modernos, tienen un navegador genérico, por lo que ni siquiera puede detectar la presencia de la clase MouseEvent.
La solución menos dolorosa aquí sería, en mi opinión, mostrar un menú en el lanzamiento (con administración 'alt' solo para usuarios del teclado) y tal vez almacenar la opción con localStorage / cookies / serveride o, de lo contrario, mantener la misma opción la próxima vez cuando llega el visitante.
fuente
Recomiendo encarecidamente contra este enfoque. Considere la pantalla táctil, dispositivos del tamaño de una computadora de escritorio, y tiene un conjunto diferente de problemas para resolver.
Haga que su aplicación sea utilizable sin un mouse (es decir, sin vista previa de desplazamiento).
fuente
Me gustaría recomendar un script que me ayudó:
Había leído y probado todo lo sugerido, sin resultados suficientes.
Luego investigué un poco más y encontré este código: device.js
Estoy usando esto en el sitio web de mi cliente, para detectar la existencia del mouse:
(
<html>
debería tenerdesktop
clase) y parece bastante bueno, y para obtenertouch
soporte, solo hago la verificación regular'ontouchend' in document
y uso la información de ambas detecciones para asumir una cosa específica que necesito.fuente
En general, es una mejor idea detectar si la función de mouseover es compatible en lugar de detectar el tipo de sistema operativo / navegador. Puede hacerlo simplemente de la siguiente manera:
Asegúrese de no hacer lo siguiente:
Este último realmente llamaría al método, en lugar de verificar su existencia.
Puede leer más aquí: http://www.quirksmode.org/js/support.html
fuente