Qual è il modo migliore per rilevare un dispositivo "touch screen" utilizzando JavaScript?


416

Ho scritto un plug-in jQuery che può essere utilizzato sia su dispositivi desktop che mobili. Mi chiedevo se esiste un modo con JavaScript per rilevare se il dispositivo ha funzionalità touchscreen. Sto usando jquery-mobile.js per rilevare gli eventi del touchscreen e funziona su iOS, Android ecc., Ma vorrei anche scrivere dichiarazioni condizionali in base al fatto che il dispositivo dell'utente abbia un touchscreen.

È possibile?


questo è il modo migliore var x = 'touchstart' in document.documentElement; console.log (x) // restituisce vero se è supportato // altrimenti restituisce falso
Risa__B

Perché questo thread è protetto se stanno ancora emergendo nuove tecniche?
Andy Hoffman,

Risposte:


139

Aggiornamento: leggi la risposta di blmstr di seguito prima di inserire un'intera libreria di rilevamento delle caratteristiche nel tuo progetto. Rilevare il supporto touch effettivo è più complesso e Modernizr copre solo un caso d'uso di base.

Modernizr è un modo eccellente e leggero per eseguire tutti i tipi di rilevamento di funzionalità su qualsiasi sito.

Aggiunge semplicemente classi all'elemento html per ogni funzione.

È quindi possibile scegliere come target queste funzionalità facilmente in CSS e JS. Per esempio:

html.touch div {
    width: 480px;
}

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

E Javascript (esempio jQuery):

$('html.touch #popup').hide();

88
Modernizr non verifica i touchscreen. Verifica l'esistenza di eventi touch nel browser. Vedi la sezione "Misc Tests" nella documentazione: modernizr.com/docs/#features-misc
Harry Love

1
puoi anche fare un test JS per l'esistenza di eventi touch se (Modernizr.touch) {/ * do touch stuff /} else {/ fine, no * /}
Anatoly G

7
Al punto di @ harrylove, da quando è uscito Windows 8, Modernizr ha erroneamente restituito tutti i browser del mio PC come compatibili con il tocco.
Anton,

3
Aggiornamento: la risposta di blmstr è migliore ed è una pura soluzione Javascript.
Alan Christopher Thomas,

1
Se Modernizr.touchritorna inaspettatamente undefined, potresti avere un Modernizr personalizzato (puoi scegliere e scegliere) senza supporto per il rilevamento di eventi touch.
Henrik N,

680

Hai provato a usare questa funzione? (Questo è lo stesso usato da Modernizr.)

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

console.log(is_touch_device());

AGGIORNAMENTO 1

document.createEvent("TouchEvent")hanno iniziato a tornare truenell'ultimo Chrome (v. 17). Modernizr lo ha aggiornato qualche tempo fa. Dai un'occhiata al test di Modernizr qui .

Aggiorna la tua funzione in questo modo per farlo funzionare:

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

console.log(is_touch_device1());

AGGIORNAMENTO 2

Ho scoperto che quanto sopra non funzionava su IE10 (restituendo false su MS Surface). Ecco la soluzione:

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());

AGGIORNAMENTO 3

'onmsgesturechange' in windowtornerà vero in alcune versioni desktop IE, quindi non è affidabile. Funziona in modo leggermente più affidabile:

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());

AGGIORNAMENTO 2018

Il tempo passa e ci sono modi nuovi e migliori per testarlo. Ho sostanzialmente estratto e semplificato il modo di Modernizr di verificarlo:

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());

Qui stanno usando la touch-enabledfunzione di query multimediale non standard , che penso sia un po 'strana e cattiva pratica. Ma hey, nel mondo reale credo che funzioni. In futuro (quando saranno supportati da tutti) queste funzionalità di media query potrebbero darti gli stessi risultati: pointere hover.

Scopri la fonte di come sta procedendo Modernizr .

Per un buon articolo che spiega i problemi con il rilevamento del tocco, vedere: Stu Cox: non è possibile rilevare un touchscreen .


20
Il doppio botto lancia un valore su un valore booleano, costringendo la funzione a restituire trueo false. Puoi leggere di più qui: stackoverflow.com/questions/4686583/…
Rob Flaherty,

2
Questo non funziona con Opera Mobile 10 o Internet Explorer Mobile 6 (Windows Mobile 6.5).
doubleJ

17
Il doppio NOT (!!) è superfluo poiché l' inoperatore valuta già un valore booleano.
Steve,

11
'onmsgesturechange'sta valutando vero anche nei dispositivi non touch (PC). window.navigator.msMaxTouchPointssembra essere più preciso. L'ho trovato qui .
Steve,

6
Sta valutando true su IE10 su Windows 8 anche se il mio schermo non ha sensori tattili. Ho aggiornato il mio vecchio laptop da Windows 7 a Windows 8.
Pwner il

120

Poiché Modernizr non rileva IE10 su Windows Phone 8 / WinRT, una semplice soluzione cross-browser è:

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

Devi solo verificare una volta poiché il dispositivo non supporta o non supporta improvvisamente il tocco, quindi memorizzalo in una variabile in modo da poterlo utilizzare più volte in modo più efficiente.


3
'onmsgesturechange' nella finestra rileva anche IE10 "desktop" su dispositivi non touch, quindi questo non è un metodo affidabile per determinare il tocco.
Matt Stow,

6
Questa risposta avrebbe dovuto essere accettata, poiché è la migliore, la più semplice e aggiornata. In una funzione credo che questo sarebbe più coerente: return !!('ontouchstart' in window) || !!('msmaxtouchpoints' in window.navigator);(per combinare entrambe le risposte) Funziona bene anche in IE10!
Yeti,

Questa dovrebbe essere la risposta accettata. 'onmsgesturechange' in windowritorna vero sul desktop IE10 anche quando il tocco è possibile
Sam Thornton

6
Tutto ciò di cui hai bisogno:function isTouchDevice() { return 'ontouchstart' in window || !!(navigator.msMaxTouchPoints);}
GFoley83

1
Persino il suggerimento di GFoleys di "ontouchstart" nella finestra || !! (navigator.msMaxTouchPoints); restituisce falsi positivi in ​​Chrome, 30 dev febbraio 2014.
Tom Andersen,

37

Utilizzando tutti i commenti sopra ho assemblato il seguente codice che funziona per le mie esigenze:

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

Ho provato questo su iPad, Android (Browser e Chrome), Blackberry Playbook, iPhone 4s, Windows Phone 8, IE 10, IE 8, IE 10 (Windows 8 con touchscreen), Opera, Chrome e Firefox.

Attualmente non funziona su Windows Phone 7 e non sono ancora riuscito a trovare una soluzione per quel browser.

Spero che qualcuno lo ritenga utile.


C'è qualche motivo che non puoi usare: function is_touch_device () {return !! ('ontouchstart' nella finestra) || !! ('msmaxtouchpoints' nel navigatore); };
Sidonaldson,

l'uso della funzione funzionerà, ma in genere mi piace usare il metodo variabile sopra, quindi viene testato una sola volta ed è più veloce quando controllo più avanti nel mio codice. Inoltre ho scoperto che dovevo provare per vedere se msMaxTouchPoints era più di 0 come IE 10 su Windows 8 senza touchscreen restituiva 0 come msMaxTouchPoints.
David,

ritorna truesul mio Firefox 32 su Windows 7 :(
vsync il

Firefox 33 e 33.1 su Windows 8 mostrano entrambi false correttamente sul mio sistema. Se aggiorni Firefox alla versione più recente, restituisce comunque true? Forse hai un dispositivo installato sul tuo computer che potrebbe far pensare erroneamente a Firefox che il tuo computer abbia toccato?
David,

>>> 'ontouchstart' nella finestra >>> true FF 51.0.1 su ubuntu
Ravi Gadhia

25

Dall'introduzione delle funzionalità dei media di interazione puoi semplicemente fare:

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

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

Aggiornamento (a causa di commenti): la soluzione sopra è quella di rilevare se un "puntatore approssimativo" - di solito un touchscreen - è il dispositivo di input principale. Nel caso in cui si desideri rilevare se un dispositivo con ad esempio un mouse ha anche un touchscreen che è possibile utilizzareany-pointer: coarse invece.

Per ulteriori informazioni, dai un'occhiata qui: Rileva che il browser non ha mouse ed è solo touch


3
Questa è di gran lunga la soluzione migliore, grazie! Anche se consiglierei di usare (pointer: coarse)come molto probabilmente stai prendendo di mira solo l'input principale. Può essere utilizzato in produzione, poiché i pochi browser non supportati sono solo desktop. C'è un ottimo articolo a riguardo su css-tricks .
Fabian von Ellerts

2
Questa è l'unica soluzione che ho testato che funziona in ogni situazione. Grazie!
kaiserkiwi,

20

Mi piace questa:

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

alert(isTouchDevice());

12
Non è necessario utilizzare un'espressione ternaria per restituire un valore booleano. Usa semplicemente l'espressione per restituire il valore booleano. function isTouchDevice(){ return (window.ontouchstart !== undefined); }
Tim Vermaelen,

1
Potresti anche semplicemente usare var isTouch = 'ontouchstart' in window;:, tuttavia questo non funziona con l'ultimo Chrome (v31), var isTouch = 'createTouch' in window.document;funziona ancora.
Olivier,

2
Come già accennato nei commenti della domanda precedentemente accettata. "Modernizr non verifica i touchscreen. Verifica l'esistenza di eventi touch nel browser". La tua funzione è tecnicamente hasTouchEvents () non isTouchDevice ()
hexalys

Tieni presente che solo test con metodi simili touchstartnon riconoscono Surface come dispositivo touch poiché IE utilizza pointerinvece gli eventi.
CookieMonster

1
Forse @Nis aveva ragione, ma in Firefox 39, restituisce correttamente falso.
Dan Dascalescu,

17

Se usi Modernizr , è molto facile da usare Modernizr.touchcome menzionato in precedenza.

Tuttavia, preferisco utilizzare una combinazione di Modernizr.touchtest utente e utente, solo per sicurezza.

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
    }

Se non usi Modernizr, puoi semplicemente sostituire la Modernizr.touchfunzione sopra con('ontouchstart' in document.documentElement)

Si noti inoltre che il test dell'agente utente iemobileoffre una gamma più ampia di dispositivi mobili Microsoft rilevati rispetto aWindows Phone .

Vedi anche questa domanda SO


8
Molti punti bonus per "fai qualcosa di permaloso" e "impossibile toccarlo"
Lee Saxon,

stai controllando più volte per gli stessi dispositivi e stai facendo più regex quando potresti usarne solo uno. inoltre, stai eseguendo regex senza distinzione tra maiuscole e minuscole ma la stringa è già in minuscolo.
Caesarsol,

1
questo dovrebbe bastare:/(iphone|ipod|ipad|android|iemobile|blackberry|bada)/.test(window.navigator.userAgent.toLowerCase())
caesarsol,

Qualche motivo per minuscole o rendere insensibili le maiuscole corrispondenti? Quando "iOS", "Android" o "IEMobile" utilizzerebbero altri involucri?
Henrik N,

14

Abbiamo provato l'implementazione di modernizr, ma il rilevamento degli eventi touch non è più coerente (IE 10 ha eventi touch sul desktop di Windows, IE 11 funziona, perché hanno lasciato cadere gli eventi touch e aggiunto l'API del puntatore).

Quindi abbiamo deciso di ottimizzare il sito Web come sito tattile purché non conosciamo il tipo di input dell'utente. Questo è più affidabile di qualsiasi altra soluzione.

Le nostre ricerche affermano che la maggior parte degli utenti desktop si sposta con il mouse sullo schermo prima di fare clic, in modo da poterli rilevare e modificare il comportamento prima che siano in grado di fare clic o passare il mouse su qualsiasi cosa.

Questa è una versione semplificata del nostro codice:

var isTouch = true;
window.addEventListener('mousemove', function mouseMoveDetector() {
    isTouch = false;
    window.removeEventListener('mousemove', mouseMoveDetector);
});

i computer oggi hanno sia il tocco che il mouse ... devi differenziare. è assolutamente da sapere se si tratta solo di tocco, mouse o entrambi. 3 stati diversi.
vsync,

1
Sì, hai ragione, ma questo è molto difficile. Nel migliore dei casi, l'applicazione è progettata per essere utilizzata da qualsiasi controller di input e non importa se l'utente ha un touchscreen, un mouse, una tastiera o tutti insieme.
Martin Lantzsch,

1
Il comportamento dell'utente ha più valore di una reale informazione sul tipo di dispositivo dell'utente. Quando sai che l'utente ha un mouse, un touchscreen e una tastiera, e allora? Gestire il comportamento (mousemove, touchmove, keydown, ecc.). Gli utenti sono in grado di cambiare il loro tipo di input in "runtime", questo è un vero problema bestiale, quando stai sviluppando una vera applicazione che viene utilizzata dalle 8 alle 5 senza ricaricare.
Martin Lantzsch,

2
+1 Pragmaticamente questa è la risposta migliore per me. Ad esempio, ho dei datagrid. Questi datagrid mostreranno una "icona di modifica" da toccare per la modifica o un menu di scelta rapida per ulteriori opzioni. Se viene rilevato lo spostamento del mouse, rimuovo l'icona (risparmia spazio sulla griglia) e gli utenti possono fare doppio clic o fare clic con il tasto destro.
prograhammer

3
chrome on touch devices attiva occasionalmente
mousemove

9

Fiddle di lavoro

L'ho raggiunto in questo modo;

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
}

non rileva il tablet Windows Surface
Dan Beaulieu,

@DanBeaulieu, per favore, puoi essere specifico per il dispositivo, perché ho Windows Phone per cui funziona benissimo, inoltre l'ho usato nella mia applicazione che è QA: ED, lo ricontraccerò di nuovo e aggiornerò la risposta. Ci scusiamo per l'inconveniente
Aamir Shahzad,

Non sono sicuro di quale anno, è un professionista di Windows Surface che appartiene a un collega. Dopo aver aggiunto modernizr, l'abbiamo fatto funzionare.
Dan Beaulieu

Questo ha segnalato correttamente Non-Touch sul mio computer Windows 7 e tocca un laptop Windows 8 con touchscreen e un telefono Android 4.4 MotoX.
Clay Nichols,

Fornisce un falso positivo in Chrome (46) sul mio Mac
Patrick Fabrizius,

9

C'è qualcosa di meglio che controllare se hanno un touchscreen, è controllare se lo stanno usando, inoltre è più facile da controllare.

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

6

Questo funziona bene anche nei tablet 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");
}
}

4

Ho usato pezzi del codice sopra per rilevare se il tocco, quindi i miei iframe fancybox si sarebbero mostrati sui computer desktop e non al tocco. Ho notato che Opera Mini per Android 4.0 si stava ancora registrando come dispositivo non touch quando si utilizzava solo il codice di blmstr. (Qualcuno sa perché?)

Ho finito per usare:

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

potresti per favore spiegare, perché non usare una singola chiamata con una sola regexp /iPhone|iPod|iPad|Android|BlackBerry/?
user907860

Opera Mini esegue il rendering sui server di Opera e non sul dispositivo stesso, quindi è un po 'strano in quel modo.
bluesmoon,

4

Il più grande "gotcha" con il tentativo di rilevare il tocco è su dispositivi ibridi che supportano sia il tocco sia il trackpad / mouse. Anche se sei in grado di rilevare correttamente se il dispositivo dell'utente supporta il tocco, ciò che devi veramente fare è rilevare quale dispositivo di input sta attualmente utilizzando l'utente . C'è una descrizione dettagliata di questa sfida e una possibile soluzione qui .

Fondamentalmente l'approccio per capire se un utente ha appena toccato lo schermo o utilizzato un mouse / trackpad è quello di registrare sia a touchstartche mouseoverevento sulla pagina:

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

Un'azione touch attiverà entrambi questi eventi, sebbene il primo ( touchstart) sia sempre il primo sulla maggior parte dei dispositivi. Quindi, contando su questa prevedibile sequenza di eventi, è possibile creare un meccanismo che aggiunge o rimuove dinamicamente una can-touchclasse nella radice del documento per riflettere l' attuale tipo di input dell'utente in questo momento sul documento:

;(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
})();

Maggiori dettagli qui .


3

Dai un'occhiata a questo post , offre uno snippet di codice davvero interessante su cosa fare quando vengono rilevati i dispositivi touch o cosa fare se viene chiamato l'evento touchstart:

$(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();
}

3

Eviterei di utilizzare la larghezza dello schermo per determinare se un dispositivo è un dispositivo touch. Ci sono touchscreen molto più grandi di 699 px, pensate a Windows 8. Navigatior.userAgent può essere utile per sovrascrivere falsi postivi.

Consiglio di dare un'occhiata a questo problema su Modernizr.

Desideri verificare se il dispositivo supporta eventi touch o è un dispositivo touch. Sfortunatamente, non è la stessa cosa.


3

No, non è possibile. Le eccellenti risposte fornite sono sempre e solo parziali, perché ogni dato metodo produrrà falsi positivi e falsi negativi. Anche il browser non sa sempre se è presente un touchscreen, a causa delle API del sistema operativo, e il fatto può cambiare durante una sessione del browser, in particolare con le disposizioni di tipo KVM.

Vedi ulteriori dettagli in questo eccellente articolo:

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

L'articolo suggerisce di riconsiderare le ipotesi che ti fanno venir voglia di rilevare i touchscreen, probabilmente sono sbagliati. (Ho controllato la mia per la mia app e le mie ipotesi erano davvero sbagliate!)

L'articolo conclude:

Per i layout, supponiamo che tutti abbiano un touchscreen. Gli utenti del mouse possono utilizzare controlli UI di grandi dimensioni molto più facilmente di quanto gli utenti touch possano utilizzare quelli piccoli. Lo stesso vale per gli stati al passaggio del mouse.

Per eventi e interazioni, supponi che chiunque possa avere un touchscreen. Implementa le interazioni tra tastiera, mouse e touch una accanto all'altra, assicurandoti che nessuna si blocchi.


3

Molti di questi funzionano ma richiedono jQuery o jinter JavaScript lamentano la sintassi. Considerando che la tua domanda iniziale richiede un modo "JavaScript" (non jQuery, non Modernizr) di risolvere questo, ecco una semplice funzione che funziona ogni volta. È anche il minimo possibile.

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

console.log(isTouchDevice());

Un ultimo vantaggio che menzionerò è che questo codice è indipendente dal framework e dal dispositivo. Godere!


function isTouchScreen() { return window.matchMedia('(hover: none)').matches;}Questo ha funzionato per me, quindi sto aggiungendo un contributo a questa risposta, poiché mi aspettavo anche un thread JS vanigliato quando Google mi ha portato qui.
Daniel Lavedonio de Lima,

2

Sembra che Chrome 24 ora supporti gli eventi touch, probabilmente per Windows 8. Quindi il codice pubblicato qui non funziona più. Invece di provare a rilevare se il tocco è supportato dal browser, ora rilevo entrambi gli eventi di tocco e clic e mi assicuro che solo uno sia chiamato:

myCustomBind = function(controlName, callback) {

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

    callback.call();
  });
};

E poi chiamandolo:

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

Spero che sia di aiuto !


1

2

Tutti i browser supportati tranne Firefox per desktop sempre VERO a causa di Firefox per desktop supportano la progettazione reattiva per gli sviluppatori anche se fai clic sul pulsante a sfioramento o no!

Spero che Mozilla risolva questo problema nella prossima versione.

Sto usando il desktop Firefox 28.

function isTouch()
{
    return !!("ontouchstart" in window) || !!(navigator.msMaxTouchPoints);
}

è ancora la versione 32.0 e non l'hanno ancora risolto! folle. perché questo non può essere commutabile ?? Ciò restituisce sempre true:(
vsync il

2

jQuery v1.11.3

Ci sono molte buone informazioni nelle risposte fornite. Ma recentemente ho trascorso molto tempo cercando di legare tutto insieme in una soluzione funzionante per realizzare due cose:

  1. Rileva che il dispositivo in uso è un dispositivo di tipo touchscreen.
  2. Rileva che il dispositivo è stato toccato.

Oltre a questo post e al rilevamento di dispositivi touchscreen con Javascript , ho trovato questo post di Patrick Lauke estremamente utile: https://hacks.mozilla.org/2013/04/detecting-touch-its-the-why-not-the-how /

Ecco il codice ...

$(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;
    }
});

Importante! Il *.on( events [, selector ] [, data ], handler )metodo deve avere un selettore, in genere un elemento, in grado di gestire l'evento "touchstart" o qualsiasi altro evento simile associato ai tocchi. In questo caso, è l'elemento del collegamento ipertestuale "a".

Ora, non è necessario gestire il normale clic del mouse in JavaScript, poiché è possibile utilizzare CSS per gestire questi eventi utilizzando i selettori per il collegamento ipertestuale "a" elemento in questo modo:

/* unvisited link */
a:link 
{

}

/* visited link */
a:visited 
{

}

/* mouse over link */
a:hover 
{

}

/* selected link */
a:active 
{

}

Nota: ci sono anche altri selettori ...


1
var isTouchScreen = 'createTouch' in document;

o

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

suppongo che sarebbe un controllo più approfondito.


3
Sarebbe bene notare che si uariferisce a navigator.userAgent. Anche il rilevamento per larghezza dello schermo può dare risultati falsi se qualcuno apre un browser in modalità non a schermo intero.
HoLyVieR,

1

Io uso:

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

in jQuery mobile 1.0.1


1

Ho anche lottato molto con diverse opzioni su come rilevare in Javascript se la pagina viene visualizzata su un dispositivo touchscreen o meno. IMO, al momento, non esiste alcuna opzione reale per rilevare correttamente l'opzione. I browser segnalano eventi tattili su macchine desktop (perché il sistema operativo potrebbe essere pronto per il tocco) o alcune soluzioni non funzionano su tutti i dispositivi mobili.

Alla fine, mi sono reso conto che stavo seguendo l'approccio sbagliato dall'inizio: se la mia pagina doveva apparire simile su dispositivi touch e non touch, forse non avrei dovuto preoccuparmi di rilevare la proprietà: il mio scenario era per disattivare le descrizioni comandi sui pulsanti dei dispositivi touch in quanto portano a doppi tocchi dove volevo un singolo tocco per attivare il pulsante.

La mia soluzione era quella di riformattare la vista in modo che non fosse necessaria una descrizione comandi su un pulsante, e alla fine non avevo bisogno di rilevare il dispositivo touch da Javascript con metodi che avevano tutti i loro svantaggi .


1

È possibile installare modernizzatore e utilizzare un semplice evento touch. Questo è molto efficace e funziona su tutti i dispositivi su cui l'ho provato, inclusa la superficie di Windows!

Ho creato 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;
    }
}

3
Benvenuti in SO! Il codice di per sé (come il codice non commentato) raramente costituisce una risposta. Puoi migliorare questa risposta aggiungendo una spiegazione dello snippet.
ebarr,

1

La risposta pratica sembra essere quella che considera il contesto:

1) Sito pubblico (nessun accesso)
Codificare l'interfaccia utente per lavorare insieme con entrambe le opzioni.

2) Sito di accesso
Acquisisci se si è verificato uno spostamento del mouse sul modulo di accesso e salvalo in un input nascosto. Il valore viene passato con le credenziali di accesso e aggiunto alla sessione dell'utente , quindi può essere utilizzato per la durata della sessione.

Jquery da aggiungere solo alla pagina di accesso:

$('#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 su @Dave Burt e +1 su @Martin Lantzsch nelle loro risposte)


1

Il problema

A causa dei dispositivi ibridi che utilizzano una combinazione di input touch e mouse, devi essere in grado dinamicamente modificare in lo stato / la variabile che controlla se un pezzo di codice deve essere eseguito se l'utente è un utente touch o meno.

Anche i dispositivi touch si attivano mousemove alla spina.

Soluzione

  1. Supponiamo che il tocco sia falso al caricamento.
  2. Attendi fino a quando un touchstartevento viene generato, quindi impostalo su true.
  3. Se il touchstart è stato attivato, aggiungi un gestore mousemove.
  4. Se il tempo tra l'attivazione di due eventi mousemove era inferiore a 20 ms, supponiamo che stiano usando un mouse come input. Rimuovi l'evento poiché non è più necessario e mousemove è un evento costoso per i dispositivi mouse.
  5. Non appena il touchstart viene nuovamente attivato (l'utente torna a utilizzare il touch), la variabile viene ripristinata su true. E ripeti il ​​processo in modo che sia determinato in modo dinamico. Se per qualche miracolo il mouse viene sparato due volte al tocco in modo assurdamente rapido (nei miei test è praticamente impossibile farlo entro 20 ms), il prossimo touchstart lo riporterà su true.

Testato su Safari iOS e Chrome per Android.

Nota: non sicuro al 100% sugli eventi puntatore per MS Surface, ecc.

Demo 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);
}

1

In realtà, ho studiato questa domanda e ho considerato tutte le situazioni. perché è un grosso problema anche per il mio progetto. Quindi raggiungo la funzione di seguito, funziona per tutte le versioni di tutti i browser su tutti i dispositivi:

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(''));
};

Suggerimento : sicuramente, ilisTouchDevicegiusto restituiscebooleanvalori.


0

Estensione supportdell'oggetto jQuery :

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

E ora puoi controllarlo ovunque, in questo modo:

if( jQuery.support.touch )
   // do touch stuff

0

Questo sembra funzionare bene per me finora:

//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)
}

0

Quando un mouse è attaccato, si può presumere con un nitrato abbastanza elevato (direi praticamente al 100%) che l'utente sposta il mouse almeno una piccola distanza dopo che la pagina è pronta, senza fare clic. Il meccanismo seguente rileva questo. Se rilevato, lo considero come un segno di supporto mancante al tocco o, se supportato, di minore importanza quando si utilizza un mouse. Si presume che il dispositivo touch sia non rilevato.

MODIFICA Questo approccio potrebbe non adattarsi a tutti gli scopi. Può essere utilizzato per controllare la funzionalità attivata in base all'interazione dell'utente sulla pagina caricata, ad esempio un visualizzatore di immagini. Il codice seguente lascerà anche l'evento mousemove associato ai dispositivi senza mouse come si distingue ora. Altri approcci potrebbero essere migliori.

All'incirca, va così (scusate per jQuery, ma simile in puro Javascript):

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;
}));
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.