Quelle est la meilleure façon de détecter un appareil à écran tactile en utilisant JavaScript?

416

J'ai écrit un plug-in jQuery à utiliser à la fois sur les appareils de bureau et mobiles. Je me demandais s'il y avait un moyen avec JavaScript pour détecter si l'appareil a une capacité d'écran tactile. J'utilise jquery-mobile.js pour détecter les événements de l'écran tactile et cela fonctionne sur iOS, Android, etc., mais j'aimerais également écrire des instructions conditionnelles selon que l'appareil de l'utilisateur dispose d'un écran tactile.

Est-ce possible?

screenm0nkey
la source
c'est la meilleure façon var x = 'touchstart' dans document.documentElement; console.log (x) // renvoie vrai si est pris en charge // sinon retourne faux
Risa__B
Pourquoi ce fil est-il protégé si de nouvelles techniques émergent encore?
Andy Hoffman

Réponses:

139

Mise à jour: veuillez lire la réponse de blmstr ci-dessous avant d' insérer une bibliothèque complète de détection de fonctionnalités dans votre projet. La détection de la prise en charge tactile réelle est plus complexe et Modernizr ne couvre qu'un cas d'utilisation de base.

Modernizr est un excellent moyen léger de faire toutes sortes de détection de fonctionnalités sur n'importe quel site.

Il ajoute simplement des classes à l'élément html pour chaque fonctionnalité.

Vous pouvez ensuite cibler ces fonctionnalités facilement en CSS et JS. Par exemple:

html.touch div {
    width: 480px;
}

html.no-touch div {
    width: auto;
}

Et Javascript (exemple jQuery):

$('html.touch #popup').hide();
Alan Christopher Thomas
la source
88
Modernizr ne teste pas les écrans tactiles. Il teste l'existence d'événements tactiles dans le navigateur. Voir la section "Tests divers" dans les documents: modernizr.com/docs/#features-misc
Harry Love
1
vous pouvez également faire un test JS pour l'existence d'événements tactiles si (Modernizr.touch) {/ * faire des trucs tactiles /} sinon {/ bien, ne pas * /}
Anatoly G
7
Au point de @ harrylove, depuis la sortie de Windows 8, Modernizr a renvoyé de manière incorrecte tous les navigateurs de mon PC comme compatibles tactiles.
Anton
3
Mise à jour: la réponse de blmstr est meilleure et est une pure solution Javascript.
Alan Christopher Thomas
1
En cas de Modernizr.touchretour inattendu undefined, vous pourriez avoir un Modernizr personnalisé (vous pouvez choisir) sans prise en charge de la détection des événements tactiles.
Henrik N
680

Avez-vous essayé d'utiliser cette fonction? (C'est le même que celui utilisé par Modernizr.)

function is_touch_device() {  
  try {  
    document.createEvent("TouchEvent");  
    return true;  
  } catch (e) {  
    return false;  
  }  
}

console.log(is_touch_device());

MISE À JOUR 1

document.createEvent("TouchEvent")ont commencé à revenir truedans le dernier chrome (v. 17). Modernizr l'a mis à jour il y a quelque temps. Consultez le test Modernizr ici .

Mettez à jour votre fonction comme ceci pour la faire fonctionner:

function is_touch_device1() {
  return 'ontouchstart' in window;
}

console.log(is_touch_device1());

MISE À JOUR 2

J'ai trouvé que ce qui précède ne fonctionnait pas sur IE10 (renvoyant faux sur MS Surface). Voici le correctif:

function is_touch_device2() {
  return 'ontouchstart' in window        // works on most browsers 
  || 'onmsgesturechange' in window;  // works on IE10 with some false positives
};

console.log(is_touch_device2());

MISE À JOUR 3

'onmsgesturechange' in windowretournera vrai dans certaines versions de bureau IE donc ce n'est pas fiable. Cela fonctionne de manière un peu plus fiable:

function is_touch_device3() {
  return !!('ontouchstart' in window        // works on most browsers 
  || navigator.maxTouchPoints);       // works on IE10/11 and Surface
};

console.log(is_touch_device3());

MISE À JOUR 2018

Le temps passe et il existe de nouvelles et meilleures façons de le tester. J'ai essentiellement extrait et simplifié la manière de vérifier de Modernizr:

function is_touch_device4() {
    
    var prefixes = ' -webkit- -moz- -o- -ms- '.split(' ');
    
    var mq = function (query) {
        return window.matchMedia(query).matches;
    }

    if (('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch) {
        return true;
    }

    // include the 'heartz' as a way to have a non matching MQ to help terminate the join
    // https://git.io/vznFH
    var query = ['(', prefixes.join('touch-enabled),('), 'heartz', ')'].join('');
    return mq(query);
}

console.log(is_touch_device4());

Ici, ils utilisent la touch-enabledfonction de requête multimédia non standard , ce qui, je pense, est un peu étrange et une mauvaise pratique. Mais bon, dans le monde réel, je suppose que ça marche. À l'avenir (lorsqu'elles seront prises en charge par tous), ces fonctionnalités de requête multimédia pourraient vous donner les mêmes résultats: pointeret hover.

Découvrez la source de la façon dont Modernizr le fait .

Pour un bon article qui explique les problèmes de détection tactile, voir: Stu Cox: vous ne pouvez pas détecter un écran tactile .

bolmaster2
la source
20
Le double coup convertit une valeur en booléen, forçant la fonction à retourner soit trueou false. Vous pouvez en savoir plus à ce sujet ici: stackoverflow.com/questions/4686583/…
Rob Flaherty
2
Cela ne fonctionne pas avec Opera Mobile 10 ou Internet Explorer Mobile 6 (Windows Mobile 6.5).
doubleJ
17
Le double NOT (!!) est superflu car l' inopérateur évalue déjà un booléen.
Steve
11
'onmsgesturechange'évalue vrai même dans les appareils non tactiles (PC). window.navigator.msMaxTouchPointssemble être plus précis. Je l'ai trouvé ici .
Steve
6
Il est évalué à vrai sur IE10 sur Windows 8 même si mon écran n'a pas de capteurs tactiles. J'ai mis à niveau mon ancien ordinateur portable de Windows 7 vers Windows 8.
Pwner
120

Comme Modernizr ne détecte pas IE10 sur Windows Phone 8 / WinRT, une solution simple et multi-navigateur est:

var supportsTouch = 'ontouchstart' in window || navigator.msMaxTouchPoints;

Vous n'avez besoin de vérifier qu'une seule fois, car l'appareil ne prend pas en charge ou ne prend pas en charge le toucher, alors stockez-le simplement dans une variable afin de pouvoir l'utiliser plusieurs fois plus efficacement.

Matt Stow
la source
3
'onmsgesturechange' dans la fenêtre détecte également IE10 "de bureau" sur les appareils non tactiles, ce n'est donc pas une méthode fiable pour déterminer le toucher.
Matt Stow
6
Cette réponse aurait dû être acceptée, car elle est la meilleure, la plus simple et la plus à jour. Dans une fonction, je pense que ce serait plus cohérent: return !!('ontouchstart' in window) || !!('msmaxtouchpoints' in window.navigator);(pour combiner les deux réponses) Fonctionne bien dans IE10 aussi!
Yeti
Ce devrait être la réponse acceptée. 'onmsgesturechange' in windowretourne vrai sur le bureau IE10 même lorsque le toucher est possible
Sam Thornton
6
Tout ce dont vous avez besoin:function isTouchDevice() { return 'ontouchstart' in window || !!(navigator.msMaxTouchPoints);}
GFoley83
1
Même la suggestion de GFoleys de 'ontouchstart' dans la fenêtre || !! (navigator.msMaxTouchPoints); retourne faussement positif dans Chrome 30 dev février 2014.
Tom Andersen
37

En utilisant tous les commentaires ci-dessus, j'ai assemblé le code suivant qui fonctionne pour mes besoins:

var isTouch = (('ontouchstart' in window) || (navigator.msMaxTouchPoints > 0));

J'ai testé cela sur iPad, Android (navigateur et Chrome), Blackberry Playbook, iPhone 4s, Windows Phone 8, IE 10, IE 8, IE 10 (Windows 8 avec écran tactile), Opera, Chrome et Firefox.

Il échoue actuellement sur Windows Phone 7 et je n'ai pas encore trouvé de solution pour ce navigateur.

J'espère que quelqu'un trouvera cela utile.

David
la source
Y a-t-il une raison que vous ne pouvez pas utiliser: function is_touch_device () {return !! ('ontouchstart' dans la fenêtre) || !! ('msmaxtouchpoints' dans le navigateur); };
sidonaldson
l'utilisation de la fonction fonctionnera mais j'aime généralement utiliser la méthode variable ci-dessus, donc elle n'est testée qu'une seule fois et est plus rapide lorsque je vérifie plus tard dans mon code. J'ai également constaté que je devais tester pour voir si msMaxTouchPoints était supérieur à 0 car IE 10 sur Windows 8 sans écran tactile renvoyait 0 comme msMaxTouchPoints.
David
revient truesur mon Firefox 32 sur Windows 7 :(
vsync
Firefox 33 et 33.1 sur Windows 8 affichent tous deux correctement faux sur mon système. Si vous mettez à niveau votre Firefox vers la dernière version, est-ce qu'il revient toujours vrai? Avez-vous peut-être un appareil installé sur votre ordinateur qui pourrait faire croire à tort à Firefox que votre ordinateur est tactile?
David
>>> 'ontouchstart' dans la fenêtre >>> true FF 51.0.1 sur ubuntu
Ravi Gadhia
25

Depuis l'introduction des fonctionnalités de médias d'interaction, vous pouvez simplement faire:

if(window.matchMedia("(pointer: coarse)").matches) {
    // touchscreen
}

https://www.w3.org/TR/mediaqueries-4/#descdef-media-any-pointer

Mise à jour (en raison des commentaires): La solution ci-dessus consiste à détecter si un "pointeur grossier" - généralement un écran tactile - est le périphérique d'entrée principal. Dans le cas où vous souhaitez détecter si un appareil avec par exemple une souris a également un écran tactile, vous pouvez utiliser à la any-pointer: coarseplace.

Pour plus d'informations, regardez ici: Détecter que le navigateur n'a pas de souris et est tactile uniquement

Blackbam
la source
3
C'est de loin la meilleure solution, merci! Bien que je recommande d'utiliser (pointer: coarse)car vous ne ciblez probablement que l'entrée principale. Peut être utilisé en production, car les quelques navigateurs non compatibles sont uniquement de bureau. Il y a un excellent article à ce sujet sur les astuces CSS .
Fabian von Ellerts
2
C'est la seule solution que j'ai testée qui fonctionne dans toutes les situations. Merci!
kaiserkiwi
20

J'aime celui la:

function isTouchDevice(){
    return typeof window.ontouchstart !== 'undefined';
}

alert(isTouchDevice());
Benny Neugebauer
la source
12
Il n'est pas nécessaire d'utiliser une expression ternaire pour renvoyer un booléen. Utilisez simplement l'expression pour renvoyer le booléen. function isTouchDevice(){ return (window.ontouchstart !== undefined); }
Tim Vermaelen
1
Vous pouvez également simplement utiliser var isTouch = 'ontouchstart' in window;:, mais cela ne fonctionne pas avec le dernier Chrome (v31), var isTouch = 'createTouch' in window.document;fonctionne toujours.
Olivier
2
Comme déjà mentionné dans les commentaires de la question précédemment acceptée. "Modernizr ne teste pas les écrans tactiles. Il teste l'existence d'événements tactiles dans le navigateur". Votre fonction est techniquement hasTouchEvents () et non isTouchDevice ()
hexalys
Notez que des méthodes similaires de test uniquement touchstartne reconnaîtront pas Surface comme un appareil tactile car IE utilise des pointerévénements à la place.
CookieMonster
1
Peut-être que @Nis avait raison, mais dans Firefox 39, il renvoie correctement false.
Dan Dascalescu
17

Si vous utilisez Modernizr , il est très facile à utiliser Modernizr.touchcomme mentionné précédemment.

Cependant, je préfère utiliser une combinaison de Modernizr.touchtests d'agent utilisateur pour des raisons de sécurité.

var deviceAgent = navigator.userAgent.toLowerCase();

var isTouchDevice = Modernizr.touch || 
(deviceAgent.match(/(iphone|ipod|ipad)/) ||
deviceAgent.match(/(android)/)  || 
deviceAgent.match(/(iemobile)/) || 
deviceAgent.match(/iphone/i) || 
deviceAgent.match(/ipad/i) || 
deviceAgent.match(/ipod/i) || 
deviceAgent.match(/blackberry/i) || 
deviceAgent.match(/bada/i));

if (isTouchDevice) {
        //Do something touchy
    } else {
        //Can't touch this
    }

Si vous n'utilisez pas Modernizr, vous pouvez simplement remplacer la Modernizr.touchfonction ci-dessus par('ontouchstart' in document.documentElement)

Notez également que le test de l'agent utilisateur iemobilevous donnera une gamme plus large d'appareils mobiles Microsoft détectés que Windows Phone.

Voir aussi cette question SO

Peter-Pan
la source
8
Beaucoup de points bonus pour "faire quelque chose de délicat" et "ne peut pas toucher à cela"
Lee Saxon
vous vérifiez plusieurs fois les mêmes appareils et effectuez plusieurs regex lorsque vous ne pouvez en utiliser qu'un. de plus, vous effectuez des expressions rationnelles insensibles à la casse, mais la chaîne est déjà en minuscules.
caesarsol
1
cela devrait suffire:/(iphone|ipod|ipad|android|iemobile|blackberry|bada)/.test(window.navigator.userAgent.toLowerCase())
caesarsol
Y a-t-il une raison pour mettre en minuscules ou rendre la correspondance insensible à la casse? Quand "iOS", "Android" ou "IEMobile" utiliseraient-ils un autre boîtier?
Henrik N
14

Nous avons essayé l'implémentation modernizr, mais la détection des événements tactiles n'est plus cohérente (IE 10 a des événements tactiles sur le bureau Windows, IE 11 fonctionne, car ils ont supprimé les événements tactiles et ajouté une api de pointeur).

Nous avons donc décidé d'optimiser le site Web en tant que site tactile tant que nous ne savons pas de quel type d'entrée l'utilisateur dispose. C'est plus fiable que toute autre solution.

Nos recherches indiquent que la plupart des utilisateurs de bureau se déplacent avec leur souris sur l'écran avant de cliquer, afin que nous puissions les détecter et modifier le comportement avant de pouvoir cliquer ou survoler quoi que ce soit.

Il s'agit d'une version simplifiée de notre code:

var isTouch = true;
window.addEventListener('mousemove', function mouseMoveDetector() {
    isTouch = false;
    window.removeEventListener('mousemove', mouseMoveDetector);
});
Martin Lantzsch
la source
les ordinateurs d'aujourd'hui ont à la fois le toucher et la souris ... vous devez faire la différence. c'est un must absolu pour savoir s'il ne s'agit que du toucher, de la souris ou des deux. 3 états différents.
vsync
1
Oui, vous avez raison, mais c'est très difficile. Dans le meilleur des cas, votre application est conçue pour être utilisée par n'importe quel contrôleur d'entrée et ne se soucie pas si l'utilisateur a un écran tactile, une souris, un clavier ou tous ensemble.
Martin Lantzsch
1
Le comportement de l'utilisateur vaut plus qu'une information réelle sur le type d'appareil dont dispose l'utilisateur. Lorsque vous savez que l'utilisateur a une souris, un écran tactile et un clavier - alors quoi? Gérer le comportement (mousemove, touchmove, keydown, etc.). Les utilisateurs sont capables de changer leur type d'entrée à "runtime", c'est un vrai problème bestial, lorsque vous développez une vraie application qui est utilisée 8 à 5 sans recharger.
Martin Lantzsch
2
+1 Pragmatiquement, c'est la meilleure réponse pour moi. Par exemple, j'ai des datagrids. Ces datagrids afficheront une "icône d'édition" à toucher pour l'édition ou un menu contextuel pour plus d'options. Si un déplacement de la souris est détecté, je supprime l'icône (économise de l'espace sur la grille) et les utilisateurs peuvent double-cliquer ou cliquer avec le bouton droit.
prograhammer
3
le chrome sur les appareils tactiles déclenche le déplacement de souris de temps en temps
pstanton
9

Violon de travail

Je l'ai réalisé comme ça;

function isTouchDevice(){
    return true == ("ontouchstart" in window || window.DocumentTouch && document instanceof DocumentTouch);
}

if(isTouchDevice()===true) {
    alert('Touch Device'); //your logic for touch device
}
else {
    alert('Not a Touch Device'); //your logic for non touch device
}
Aamir Shahzad
la source
ne détecte pas la tablette de surface Windows
Dan Beaulieu
@DanBeaulieu pouvez-vous s'il vous plaît être spécifique à l'appareil, car j'ai un téléphone Windows pour lequel cela fonctionne bien, je l'ai également utilisé dans mon application qui est QA: ED, je vais le revérifier et mettre à jour la réponse. Désolé pour le dérangement
Aamir Shahzad
Je ne sais pas quelle année, c'est un pro de surface Windows qui appartient à un collègue. Après avoir ajouté modernizr, nous l'avons fait fonctionner.
Dan Beaulieu
Cela a correctement signalé Non-Touch sur ma machine Windows 7 et tactile sur un ordinateur portable Windows 8 avec écran tactile et un téléphone Android 4.4 MotoX.
Clay Nichols
Donne un faux positif dans Chrome (46) sur mon Mac
Patrick Fabrizius
9

Il y a quelque chose de mieux que de vérifier s'ils ont un écran tactile, c'est de vérifier s'ils l'utilisent, et c'est plus facile à vérifier.

if (window.addEventListener) {
    var once = false;
    window.addEventListener('touchstart', function(){
        if (!once) {
            once = true;
            // Do what you need for touch-screens only
        }
    });
}
Ivan Castellanos
la source
6

Celui-ci fonctionne bien même dans les tablettes Windows Surface !!!

function detectTouchSupport {
msGesture = window.navigator && window.navigator.msPointerEnabled && window.MSGesture,
touchSupport = (( "ontouchstart" in window ) || msGesture || window.DocumentTouch &&     document instanceof DocumentTouch);
if(touchSupport) {
    $("html").addClass("ci_touch");
}
else {
    $("html").addClass("ci_no_touch");
}
}
Sathiyamoorthy
la source
4

J'ai utilisé des morceaux du code ci-dessus pour détecter s'il était tactile, donc mes iframes fancybox s'afficheraient sur les ordinateurs de bureau et non sur le toucher. J'ai remarqué que Opera Mini pour Android 4.0 s'enregistrait toujours en tant qu'appareil non tactile lors de l'utilisation du code de blmstr seul. (Quelqu'un sait-il pourquoi?)

J'ai fini par utiliser:

<script>
$(document).ready(function() {
    var ua = navigator.userAgent;
    function is_touch_device() { 
        try {  
            document.createEvent("TouchEvent");  
            return true;  
        } catch (e) {  
            return false;  
        }  
    }

    if ((is_touch_device()) || ua.match(/(iPhone|iPod|iPad)/) 
    || ua.match(/BlackBerry/) || ua.match(/Android/)) {
        // Touch browser
    } else {
        // Lightbox code
    }
});
</script>
Aimé
la source
pourriez-vous expliquer pourquoi vous ne devez pas utiliser un seul appel de correspondance avec une seule expression rationnelle /iPhone|iPod|iPad|Android|BlackBerry/?
user907860
Opera Mini effectue le rendu sur les serveurs d'Opera et non sur l'appareil lui-même, donc c'est un peu bizarre de cette façon.
bluesmoon
4

Le plus gros problème avec la détection du toucher concerne les appareils hybrides qui prennent en charge le toucher et le trackpad / souris. Même si vous êtes en mesure de détecter correctement si le périphérique de l'utilisateur prend en charge le toucher, ce que vous devez vraiment faire est de détecter le périphérique d'entrée que l'utilisateur utilise actuellement . Il y a une description détaillée de ce défi et une solution possible ici .

Fondamentalement, l'approche pour déterminer si un utilisateur vient de toucher l'écran ou a plutôt utilisé une souris / un pavé tactile consiste à enregistrer à la fois un événement touchstartet un mouseoverévénement sur la page:

document.addEventListener('touchstart', functionref, false) // on user tap, "touchstart" fires first
document.addEventListener('mouseover', functionref, false) // followed by mouse event, ie: "mouseover"

Une action tactile déclenchera ces deux événements, bien que le premier ( touchstart) soit toujours le premier sur la plupart des appareils. Ainsi, en comptant sur cette séquence d'événements prévisible, vous pouvez créer un mécanisme qui ajoute ou supprime dynamiquement une can-touchclasse à la racine du document pour refléter le type d'entrée actuel de l'utilisateur à ce moment sur le document:

;(function(){
    var isTouch = false //var to indicate current input type (is touch versus no touch) 
    var isTouchTimer 
    var curRootClass = '' //var indicating current document root class ("can-touch" or "")
     
    function addtouchclass(e){
        clearTimeout(isTouchTimer)
        isTouch = true
        if (curRootClass != 'can-touch'){ //add "can-touch' class if it's not already present
            curRootClass = 'can-touch'
            document.documentElement.classList.add(curRootClass)
        }
        isTouchTimer = setTimeout(function(){isTouch = false}, 500) //maintain "istouch" state for 500ms so removetouchclass doesn't get fired immediately following a touch event
    }
     
    function removetouchclass(e){
        if (!isTouch && curRootClass == 'can-touch'){ //remove 'can-touch' class if not triggered by a touch event and class is present
            isTouch = false
            curRootClass = ''
            document.documentElement.classList.remove('can-touch')
        }
    }
     
    document.addEventListener('touchstart', addtouchclass, false) //this event only gets called when input type is touch
    document.addEventListener('mouseover', removetouchclass, false) //this event gets called when input type is everything from touch to mouse/ trackpad
})();

Plus de détails ici .

bouffées de coco
la source
3

Consultez cet article , il donne un très bel extrait de code pour savoir quoi faire lorsque des appareils tactiles sont détectés ou quoi faire si un événement touchstart est appelé:

$(function(){
  if(window.Touch) {
    touch_detect.auto_detected();
  } else {
    document.ontouchstart = touch_detect.surface;
  }
}); // End loaded jQuery
var touch_detect = {
  auto_detected: function(event){
    /* add everything you want to do onLoad here (eg. activating hover controls) */
    alert('this was auto detected');
    activateTouchArea();
  },
  surface: function(event){
    /* add everything you want to do ontouchstart here (eg. drag & drop) - you can fire this in both places */
    alert('this was detected by touching');
    activateTouchArea();
  }
}; // touch_detect
function activateTouchArea(){
  /* make sure our screen doesn't scroll when we move the "touchable area" */
  var element = document.getElementById('element_id');
  element.addEventListener("touchstart", touchStart, false);
}
function touchStart(event) {
  /* modularize preventing the default behavior so we can use it again */
  event.preventDefault();
}
Safran Ali
la source
3

J'éviterais d'utiliser la largeur de l'écran pour déterminer si un appareil est un appareil tactile. Il y a des écrans tactiles beaucoup plus grands que 699px, pensez à Windows 8. Navigatior.userAgent peut être agréable pour remplacer les faux positifs.

Je recommanderais de vérifier ce problème sur Modernizr.

Voulez-vous tester si l'appareil prend en charge les événements tactiles ou s'il s'agit d'un appareil tactile. Malheureusement, ce n'est pas la même chose.

hybride
la source
3

Non, ce n'est pas possible. Les excellentes réponses données ne sont que partielles, car toute méthode donnée produira des faux positifs et des faux négatifs. Même le navigateur ne sait pas toujours si un écran tactile est présent, en raison des API du système d'exploitation, et le fait peut changer pendant une session de navigateur, en particulier avec des dispositions de type KVM.

Voir plus de détails dans cet excellent article:

http://www.stucox.com/blog/you-cant-detect-a-touchscreen/

L'article vous suggère de reconsidérer les hypothèses qui vous donnent envie de détecter les écrans tactiles, elles sont probablement fausses. (J'ai vérifié la mienne pour mon application et mes hypothèses étaient en effet erronées!)

L'article conclut:

Pour les mises en page, supposons que tout le monde dispose d'un écran tactile. Les utilisateurs de souris peuvent utiliser les grands contrôles de l'interface utilisateur beaucoup plus facilement que les utilisateurs tactiles peuvent utiliser les petits. Il en va de même pour les états stationnaires.

Pour les événements et les interactions, supposons que n'importe qui puisse avoir un écran tactile. Implémentez les interactions clavier, souris et tactile côte à côte, en vous assurant qu'aucune ne se bloque.

Dave Burt
la source
3

Beaucoup de ces travaux mais nécessitent soit jQuery, soit des linters javascript se plaignent de la syntaxe. Considérant que votre question initiale demande une manière "JavaScript" (pas jQuery, pas Modernizr) de résoudre cela, voici une fonction simple qui fonctionne à chaque fois. C'est aussi aussi minime que possible.

function isTouchDevice() {
    return !!window.ontouchstart;
}

console.log(isTouchDevice());

Un dernier avantage que je mentionnerai est que ce code est indépendant du framework et du périphérique. Prendre plaisir!

seanforyou23
la source
function isTouchScreen() { return window.matchMedia('(hover: none)').matches;}Cela a fonctionné pour moi, donc j'ajoute ici une contribution à cette réponse, car je m'attendais également à un fil JS vanille lorsque Google m'a amené ici.
Daniel Lavedonio de Lima
2

Il semble que Chrome 24 prenne désormais en charge les événements tactiles, probablement pour Windows 8. Le code publié ici ne fonctionne donc plus. Au lieu d'essayer de détecter si le toucher est pris en charge par le navigateur, je lie maintenant les événements de toucher et de clic et je m'assure qu'un seul est appelé:

myCustomBind = function(controlName, callback) {

  $(controlName).bind('touchend click', function(e) {
    e.stopPropagation();
    e.preventDefault();

    callback.call();
  });
};

Et puis l'appeler:

myCustomBind('#mnuRealtime', function () { ... });

J'espère que cela t'aides !

wizmagister
la source
1
Discussion connexe, stackoverflow.com/questions/12566306/…
Air
2

Tous les navigateurs pris en charge, à l'exception de Firefox pour ordinateur de bureau, sont toujours VRAIS, car Firefox pour la conception de support de bureau pour le développeur, même si vous cliquez sur le bouton tactile ou non!

J'espère que Mozilla corrigera cela dans la prochaine version.

J'utilise le bureau Firefox 28.

function isTouch()
{
    return !!("ontouchstart" in window) || !!(navigator.msMaxTouchPoints);
}
xicooc
la source
c'est toujours la version 32.0 et ils ne l'ont pas encore corrigé! insensé. pourquoi cela ne peut-il pas être basculé ?? Cela revient toujours true:(
vsync
2

jQuery v1.11.3

Il y a beaucoup de bonnes informations dans les réponses fournies. Mais récemment, j'ai passé beaucoup de temps à essayer de tout lier ensemble dans une solution de travail pour accomplir deux choses:

  1. Détectez que l'appareil utilisé est un appareil de type écran tactile.
  2. Détectez que l'appareil a été tapé.

Outre ce message et la détection des appareils à écran tactile avec Javascript , j'ai trouvé ce message de Patrick Lauke extrêmement utile: https://hacks.mozilla.org/2013/04/detecting-touch-its-the-why-not-the-how /

Voici le code ...

$(document).ready(function() {
//The page is "ready" and the document can be manipulated.

    if (('ontouchstart' in window) || (navigator.maxTouchPoints > 0) || (navigator.msMaxTouchPoints > 0))
    {
      //If the device is a touch capable device, then...
      $(document).on("touchstart", "a", function() {

        //Do something on tap.

      });
    }
    else
    {
      null;
    }
});

Important! La *.on( events [, selector ] [, data ], handler )méthode doit avoir un sélecteur, généralement un élément, qui peut gérer l'événement "touchstart", ou tout autre événement similaire associé aux touches. Dans ce cas, c'est l'élément hyperlien "a".

Maintenant, vous n'avez pas besoin de gérer le clic de souris normal en JavaScript, car vous pouvez utiliser CSS pour gérer ces événements en utilisant des sélecteurs pour l'élément de lien hypertexte "a" comme ceci:

/* unvisited link */
a:link 
{

}

/* visited link */
a:visited 
{

}

/* mouse over link */
a:hover 
{

}

/* selected link */
a:active 
{

}

Remarque: Il existe également d'autres sélecteurs ...

serge-k
la source
1
var isTouchScreen = 'createTouch' in document;

ou

var isTouchScreen = 'createTouch' in document || screen.width <= 699 || 
    ua.match(/(iPhone|iPod|iPad)/) || ua.match(/BlackBerry/) || 
    ua.match(/Android/);

serait une vérification plus approfondie, je suppose.

samuel segal
la source
3
Il serait bon de noter que cela uafait référence navigator.userAgent. De plus, la détection par largeur d'écran peut donner de faux résultats si quelqu'un ouvre un navigateur en mode non plein écran.
HoLyVieR
1

J'utilise:

if(jQuery.support.touch){
    alert('Touch enabled');
}

dans jQuery mobile 1.0.1

marque
la source
1

J'ai également eu beaucoup de mal avec différentes options sur la façon de détecter en Javascript si la page est affichée sur un appareil à écran tactile ou non. IMO, pour l'instant, il n'existe aucune option réelle pour détecter correctement l'option. Les navigateurs signalent les événements tactiles sur les ordinateurs de bureau (car le système d'exploitation peut être prêt pour le toucher), ou certaines solutions ne fonctionnent pas sur tous les appareils mobiles.

En fin de compte, j'ai réalisé que je suivais la mauvaise approche depuis le début: si ma page devait ressembler sur des appareils tactiles et non tactiles, je ne devrais peut-être pas avoir à me soucier de détecter la propriété du tout: mon scénario était pour désactiver les info-bulles sur les boutons sur les appareils tactiles car elles mènent à des tapotements où je voulais un seul tap pour activer le bouton.

Ma solution a été de refactoriser la vue afin qu'aucune info-bulle ne soit nécessaire sur un bouton, et finalement je n'ai pas eu besoin de détecter le périphérique tactile à partir de Javascript avec des méthodes qui ont toutes leurs inconvénients .

Michael
la source
1

Vous pouvez installer le moderniseur et utiliser un simple événement tactile. C'est très efficace et fonctionne sur tous les appareils sur lesquels j'ai testé, y compris la surface des fenêtres!

J'ai créé un jsFiddle

function isTouchDevice(){
    if(Modernizr.hasEvent('touchstart') || navigator.userAgent.search(/Touch/i) != -1){
         alert("is touch");
            return true;
         }else{
            alert("is not touch");
            return false;
    }
}
Endjeechner
la source
3
Bienvenue chez SO! Le code en lui-même (comme le code non commenté) constitue rarement une réponse. Vous pouvez améliorer cette réponse en ajoutant une explication de l'extrait.
ebarr
1

La réponse pratique semble être celle qui considère le contexte:

1) Site public (pas de connexion)
Codez l'interface utilisateur pour travailler avec les deux options ensemble.

2) Site de connexion
Capturez si un déplacement de la souris s'est produit sur le formulaire de connexion et enregistrez-le dans une entrée cachée. La valeur est transmise avec les informations d'identification de connexion et ajoutée à la session de l'utilisateur , afin qu'elle puisse être utilisée pendant la durée de la session.

Jquery à ajouter à la page de connexion uniquement:

$('#istouch').val(1); // <-- value will be submitted with login form

if (window.addEventListener) {
    window.addEventListener('mousemove', function mouseMoveListener(){
        // Update hidden input value to false, and stop listening
        $('#istouch').val(0); 
        window.removeEventListener('mousemove', mouseMoveListener);
    });
} 

(+1 à @Dave Burt et +1 à @Martin Lantzsch sur leurs réponses)

prograhammer
la source
1

Le problème

En raison des appareils hybrides qui utilisent une combinaison de saisie tactile et de souris, vous devez pouvoir modifier dynamiquement l'état / la variable qui contrôle si un morceau de code doit s'exécuter si l'utilisateur est un utilisateur tactile ou non.

Les appareils tactiles se déclenchent également mousemoveau robinet.

Solution

  1. Supposons que le toucher soit faux à la charge.
  2. Attendez qu'un touchstartévénement se déclenche, puis définissez-le sur true.
  3. Si le démarrage tactile a été déclenché, ajoutez un gestionnaire de déplacement de souris.
  4. Si le délai entre deux événements de déplacement de souris a été inférieur à 20 ms, supposez qu'ils utilisent une souris comme entrée. Supprimez l'événement car il n'est plus nécessaire et mousemove est un événement coûteux pour les souris.
  5. Dès que le démarrage tactile est à nouveau déclenché (l'utilisateur a recommencé à utiliser le toucher), la variable est redéfinie sur true. Et répétez le processus pour qu'il soit déterminé de manière dynamique. Si, par miracle, le déplacement de la souris est tiré deux fois au toucher de manière absurde et rapide (dans mes tests, il est pratiquement impossible de le faire dans les 20 ms), le prochain contact tactile le ramènera à vrai.

Testé sur Safari iOS et Chrome pour Android.

Remarque: pas sûr à 100% des événements de pointeur pour MS Surface, etc.

Démo Codepen


const supportsTouch = 'ontouchstart' in window;
let isUsingTouch = false;

// `touchstart`, `pointerdown`
const touchHandler = () => {
  isUsingTouch = true;
  document.addEventListener('mousemove', mousemoveHandler);
};

// use a simple closure to store previous time as internal state
const mousemoveHandler = (() => {
  let time;

  return () => {
    const now = performance.now();

    if (now - time < 20) {
      isUsingTouch = false;
      document.removeEventListener('mousemove', mousemoveHandler);
    }

    time = now;
  }
})();

// add listeners
if (supportsTouch) {
  document.addEventListener('touchstart', touchHandler);
} else if (navigator.maxTouchPoints || navigator.msMaxTouchPoints) {
  document.addEventListener('pointerdown', touchHandler);
}
glacial
la source
1

En fait, j'ai fait des recherches sur cette question et je considère toutes les situations. car c'est aussi un gros problème sur mon projet. J'atteins donc la fonction ci-dessous, elle fonctionne pour toutes les versions de tous les navigateurs sur tous les appareils:

const isTouchDevice = () => {
  const prefixes = ['', '-webkit-', '-moz-', '-o-', '-ms-', ''];
  const mq = query => window.matchMedia(query).matches;

  if (
    'ontouchstart' in window ||
    (window.DocumentTouch && document instanceof DocumentTouch)
  ) {
    return true;
  }
  return mq(['(', prefixes.join('touch-enabled),('), 'heartz', ')'].join(''));
};

Astuce : Certainement, leisTouchDeviceretourne juste desbooleanvaleurs.

AmerllicA
la source
0

supportObjet jQuery étendu :

jQuery.support.touch = 'ontouchend' in document;

Et maintenant, vous pouvez le vérifier n'importe où, comme ceci:

if( jQuery.support.touch )
   // do touch stuff
vsync
la source
0

Jusqu'à présent, cela semble bien fonctionner:

//Checks if a touch screen
is_touch_screen = 'ontouchstart' in document.documentElement;

if (is_touch_screen) {
  // Do something if a touch screen
}
else {
  // Not a touch screen (i.e. desktop)
}
Lewis James-Odwin
la source
0

Lorsqu'une souris est connectée, on peut supposer avec un taux de réussite assez élevé (je dirais pratiquement 100%) que l'utilisateur déplace la souris au moins une petite distance après que la page est prête - sans aucun clic. Le mécanisme ci-dessous le détecte. S'il est détecté, je considère cela comme un signe de manque de prise en charge tactile ou, s'il est pris en charge, d'importance mineure lorsqu'une souris est utilisée. L'appareil tactile est supposé s'il n'est pas détecté.

MODIFIER Cette approche peut ne pas convenir à tous les objectifs. Il peut être utilisé pour contrôler les fonctionnalités activées en fonction de l'interaction de l'utilisateur sur la page chargée, par exemple une visionneuse d'images. Le code ci-dessous laissera également l'événement mousemove lié aux appareils sans souris tel qu'il se distingue maintenant. D'autres approches peuvent être meilleures.

En gros, ça se passe comme ça (désolé pour jQuery, mais similaire en Javascript pur):

var mousedown, first, second = false;
var ticks = 10;
$(document).on('mousemove', (function(e) {
    if(UI.mousechecked) return;
    if(!first) {
        first = e.pageX;
        return;
        }
    if(!second && ticks-- === 0) {
        second = e.pageX;
        $(document).off('mousemove'); // or bind it to somewhat else
        }
    if(first  && second  && first !== second && !mousedown){
        // set whatever flags you want
        UI.hasmouse = true;
        UI.touch = false;
        UI.mousechecked = true;
    }

    return;
}));
$(document).one('mousedown', (function(e) {
    mousedown = true;
    return;
}));
$(document).one('mouseup', (function(e) {
    mousedown = false;
    return;
}));
cglow
la source