Apa cara terbaik untuk mendeteksi perangkat 'layar sentuh' menggunakan JavaScript?

416

Saya telah menulis plug-in jQuery yang digunakan pada desktop dan perangkat seluler. Saya bertanya-tanya apakah ada cara dengan JavaScript untuk mendeteksi apakah perangkat memiliki kemampuan layar sentuh. Saya menggunakan jquery-mobile.js untuk mendeteksi acara layar sentuh dan berfungsi di iOS, Android, dll., Tetapi saya juga ingin menulis pernyataan bersyarat berdasarkan apakah perangkat pengguna memiliki layar sentuh.

Apakah itu mungkin?

screenm0nkey
sumber
ini adalah cara yang lebih baik var x = 'touchstart' di document.documentElement; console.log (x) // return true jika didukung // else return false
Risa__B
Mengapa utas ini dilindungi jika teknik baru masih muncul?
Andy Hoffman

Jawaban:

139

Pembaruan: Silakan baca jawaban blmstr di bawah ini sebelum menarik seluruh pustaka pendeteksian fitur ke proyek Anda. Mendeteksi dukungan sentuh yang sebenarnya lebih kompleks, dan Modernizr hanya mencakup kasus penggunaan dasar.

Modernizr adalah cara yang hebat dan ringan untuk melakukan semua jenis deteksi fitur di situs mana pun.

Itu hanya menambahkan kelas ke elemen html untuk setiap fitur.

Anda kemudian dapat menargetkan fitur-fitur tersebut dengan mudah di CSS dan JS. Sebagai contoh:

html.touch div {
    width: 480px;
}

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

Dan Javascript (contoh jQuery):

$('html.touch #popup').hide();
Alan Christopher Thomas
sumber
88
Modernizr tidak menguji layar sentuh. Ini menguji keberadaan acara sentuh di browser. Lihat bagian "Tes Lain-lain" dalam dokumen: modernizr.com/docs/#features-misc
Harry Love
1
Anda juga dapat melakukan uji JS untuk keberadaan acara sentuh jika (Modernizr.touch) {/ * melakukan hal-hal sentuh /} selain itu {/ baik, jangan * /}
Anatoly G
7
Untuk titik @ harrylove, sejak Windows 8 keluar, Modernizr telah salah mengembalikan semua browser PC saya sebagai yang kompatibel dengan sentuhan.
Anton
3
Pembaruan: jawaban blmstr lebih baik, dan merupakan solusi Javascript murni.
Alan Christopher Thomas
1
Jika Modernizr.touchtiba-tiba kembali undefined, Anda mungkin memiliki Modernizr khusus (Anda bisa memilih dan memilih) tanpa dukungan untuk deteksi Acara Sentuh.
Henrik N
680

Sudahkah Anda mencoba menggunakan fungsi ini? (Ini sama dengan yang digunakan Modernizr.)

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

console.log(is_touch_device());

PEMBARUAN 1

document.createEvent("TouchEvent")sudah mulai kembali truedi chrome terbaru (ay. 17). Modernizr memperbarui ini beberapa waktu yang lalu. Periksa tes Modernizr di sini .

Perbarui fungsi Anda seperti ini untuk membuatnya berfungsi:

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

console.log(is_touch_device1());

PEMBARUAN 2

Saya menemukan bahwa di atas tidak berfungsi pada IE10 (mengembalikan false pada MS Surface). Inilah solusinya:

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

PEMBARUAN 3

'onmsgesturechange' in windowakan mengembalikan true di beberapa versi desktop IE jadi itu tidak dapat diandalkan. Ini bekerja sedikit lebih andal:

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

PEMBARUAN 2018

Waktu berlalu dan ada cara-cara baru dan lebih baik untuk menguji ini. Saya pada dasarnya telah mengekstraksi dan menyederhanakan cara Modernizr untuk memeriksanya:

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

Di sini mereka menggunakan touch-enabledfitur permintaan media non-standar , yang menurut saya agak aneh dan praktik buruk. Tapi hei, di dunia nyata kurasa itu berhasil. Di masa depan (ketika mereka didukung oleh semua) fitur-fitur permintaan media tersebut dapat memberi Anda hasil yang sama: pointerdanhover .

Lihatlah sumber bagaimana Modernizr melakukannya .

Untuk artikel bagus yang menjelaskan masalah dengan deteksi sentuh, lihat: Stu Cox: Anda Tidak Dapat Mendeteksi Layar Sentuh .

bolmaster2
sumber
20
Bang ganda melemparkan nilai ke boolean, memaksa fungsi untuk mengembalikan salah satu trueatau false. Anda dapat membaca lebih lanjut tentang hal ini di sini: stackoverflow.com/questions/4686583/…
Rob Flaherty
2
Ini tidak berfungsi dengan Opera Mobile 10 atau Internet Explorer Mobile 6 (Windows Mobile 6.5).
doubleJ
17
Double NOT (!!) berlebihan karena inoperator sudah mengevaluasi ke boolean.
Steve
11
'onmsgesturechange'sedang mengevaluasi true bahkan dalam perangkat non-sentuh (PC). window.navigator.msMaxTouchPointstampaknya lebih akurat. Ditemukan di sini .
Steve
6
Ini mengevaluasi true pada IE10 pada Windows 8 meskipun layar saya tidak memiliki sensor sentuh. Saya
memutakhirkan
120

Karena Modernizr tidak mendeteksi IE10 pada Windows Phone 8 / WinRT, solusi lintas-browser yang sederhana adalah:

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

Anda hanya perlu memeriksa sekali karena perangkat tidak akan tiba-tiba mendukung atau tidak mendukung sentuhan, jadi simpan saja dalam variabel sehingga Anda dapat menggunakannya beberapa kali lebih efisien.

Matt Stow
sumber
3
'onmsgesturechange' di jendela juga mendeteksi "desktop" IE10 pada perangkat non-sentuh, jadi ini bukan metode yang andal untuk menentukan sentuhan.
Matt Stow
6
Jawaban ini seharusnya diterima, karena yang terbaik dan paling sederhana dan terkini. Dalam suatu fungsi saya percaya ini akan lebih konsisten: return !!('ontouchstart' in window) || !!('msmaxtouchpoints' in window.navigator);(untuk menggabungkan kedua jawaban) Bekerja dengan baik di IE10 juga!
Yeti
Ini harus menjadi jawaban yang diterima. 'onmsgesturechange' in windowmengembalikan true pada desktop IE10 bahkan ketika sentuhan dimungkinkan
Sam Thornton
6
Yang Anda butuhkan:function isTouchDevice() { return 'ontouchstart' in window || !!(navigator.msMaxTouchPoints);}
GFoley83
1
Bahkan GFoleys menyarankan 'ontouchstart' di jendela || !! (navigator.msMaxTouchPoints); mengembalikan fals positif di Chrome 30 dev Feb 2014.
Tom Andersen
37

Dengan menggunakan semua komentar di atas, saya telah mengumpulkan kode berikut yang berfungsi untuk kebutuhan saya:

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

Saya telah menguji ini di iPad, Android (Browser dan Chrome), Blackberry Playbook, iPhone 4s, Windows Phone 8, IE 10, IE 8, IE 10 (Windows 8 dengan Touchscreen), Opera, Chrome dan Firefox.

Saat ini gagal pada Windows Phone 7 dan saya belum dapat menemukan solusi untuk browser itu.

Semoga seseorang menemukan ini berguna.

David
sumber
Apakah ada alasan Anda tidak dapat menggunakan: function is_touch_device () {return !! ('ontouchstart' di jendela) || !! ('msmaxtouchpoints' di navigator); };
sidonaldson
menggunakan fungsi akan bekerja tetapi saya umumnya suka menggunakan metode variabel di atas sehingga hanya akan diuji sekali dan lebih cepat ketika saya periksa nanti dalam kode saya. Saya juga menemukan bahwa saya perlu menguji untuk melihat apakah msMaxTouchPoints lebih dari 0 karena IE 10 pada Windows 8 tanpa layar sentuh mengembalikan 0 sebagai msMaxTouchPoints.
David
kembali truepada Firefox 32 saya di windows 7 :(
vsync
Firefox 33 dan 33.1 di Windows 8 keduanya menunjukkan false dengan benar di sistem saya. Jika Anda meningkatkan versi Firefox Anda ke versi terbaru, apakah masih mengembalikan true? Apakah Anda mungkin memiliki perangkat yang diinstal pada mesin Anda yang dapat membuat Firefox salah berpikir bahwa mesin Anda memiliki sentuhan?
David
>>> 'ontouchstart' di jendela >>> true FF 51.0.1 di ubuntu
Ravi Gadhia
25

Karena pengenalan fitur media interaksi, Anda dapat melakukannya:

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

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

Pembaruan (karena komentar): Solusi di atas adalah untuk mendeteksi apakah "pointer kasar" - biasanya layar sentuh - adalah perangkat input utama. Jika Anda ingin mendeteksi jika perangkat dengan mouse misalnya juga memiliki layar sentuh yang dapat Anda gunakanany-pointer: coarse .

Untuk informasi lebih lanjut lihat di sini: Mendeteksi bahwa browser tidak memiliki mouse dan hanya sentuhan

Blackbam
sumber
3
Sejauh ini ini adalah solusi terbaik, terima kasih! Meskipun saya akan merekomendasikan menggunakan (pointer: coarse)karena Anda kemungkinan besar hanya menargetkan input utama. Dapat digunakan dalam produksi, karena beberapa browser yang tidak mendukung adalah desktop saja. Ada artikel bagus tentang ini pada trik-css .
Fabian von Ellerts
2
Ini adalah satu-satunya solusi yang saya uji yang bekerja di setiap situasi. Terima kasih!
kaiserkiwi
20

Saya suka yang ini:

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

alert(isTouchDevice());
Benny Neugebauer
sumber
12
Tidak perlu menggunakan ekspresi ternary untuk mengembalikan boolean. Cukup gunakan ekspresi untuk mengembalikan boolean. function isTouchDevice(){ return (window.ontouchstart !== undefined); }
Tim Vermaelen
1
Anda juga bisa menggunakan var isTouch = 'ontouchstart' in window;:, namun ini tidak berfungsi dengan Chrome terbaru (v31), var isTouch = 'createTouch' in window.document;masih berfungsi.
Olivier
2
Seperti yang sudah disebutkan di komentar dari pertanyaan yang diterima sebelumnya. "Modernizr tidak menguji layar sentuh. Ini menguji keberadaan acara sentuh di browser". Fungsi Anda secara teknis hasTouchEvents () bukan isTouchDevice ()
hexalys
Perhatikan bahwa pengujian metode serupa hanya touchstartakan gagal mengenali Permukaan sebagai perangkat sentuh karena IE menggunakan pointerperistiwa.
CookieMonster
1
Mungkin @Nis benar, tetapi di Firefox 39, itu benar kembali salah.
Dan Dascalescu
17

Jika Anda menggunakan Modernizr , sangat mudah digunakan Modernizr.touchseperti yang disebutkan sebelumnya.

Namun, saya lebih suka menggunakan kombinasi Modernizr.touchdan pengujian agen pengguna, hanya agar aman.

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
    }

Jika Anda tidak menggunakan Modernizr, Anda cukup mengganti Modernizr.touchfungsi di atas dengan('ontouchstart' in document.documentElement)

Perhatikan juga bahwa pengujian agen pengguna iemobileakan memberi Anda jangkauan yang lebih luas dari perangkat seluler Microsoft yang terdeteksi daripadaWindows Phone .

Lihat juga pertanyaan SO ini

Peter Pan
sumber
8
Banyak poin bonus untuk "melakukan sesuatu yang sensitif" dan "tidak bisa menyentuh ini"
Lee Saxon
Anda memeriksa beberapa kali untuk perangkat yang sama, dan melakukan beberapa Regex saat Anda hanya bisa menggunakan satu. ditambah, Anda melakukan regex case-insensitive tetapi string sudah lebih kecil.
caesarsol
1
ini sudah cukup:/(iphone|ipod|ipad|android|iemobile|blackberry|bada)/.test(window.navigator.userAgent.toLowerCase())
caesarsol
Ada alasan untuk membuat huruf kecil atau membuat huruf besar-kecil yang cocok? Kapan "iOS", "Android" atau "IEMobile" menggunakan casing lain?
Henrik N
14

Kami mencoba implementasi modernizr, tetapi mendeteksi acara sentuh tidak konsisten lagi (IE 10 memiliki acara sentuh di desktop windows, IE 11 berfungsi, karena acara sentuh yang sudah dijatuhkan dan ditambahkan pointer api).

Jadi kami memutuskan untuk mengoptimalkan situs web sebagai situs sentuh selama kami tidak tahu jenis input apa yang dimiliki pengguna. Ini lebih dapat diandalkan daripada solusi lainnya.

Penelitian kami mengatakan, bahwa sebagian besar pengguna desktop bergerak dengan mouse mereka di atas layar sebelum mereka mengklik, sehingga kami dapat mendeteksi mereka dan mengubah perilaku sebelum mereka dapat mengklik atau mengarahkan apa pun.

Ini adalah versi sederhana dari kode kami:

var isTouch = true;
window.addEventListener('mousemove', function mouseMoveDetector() {
    isTouch = false;
    window.removeEventListener('mousemove', mouseMoveDetector);
});
Martin Lantzsch
sumber
komputer saat ini memiliki sentuhan dan mouse ... Anda harus membedakan. itu mutlak harus tahu apakah itu hanya sentuhan, mouse, atau keduanya. 3 negara bagian yang berbeda.
vsync
1
Ya Anda benar, tetapi ini sangat sulit. Dalam kasus terbaik aplikasi Anda dirancang untuk digunakan oleh pengontrol input dan tidak peduli jika pengguna memiliki layar sentuh, mouse, keyboard atau semuanya.
Martin Lantzsch
1
Perilaku pengguna lebih bernilai daripada informasi nyata tentang jenis perangkat yang dimiliki pengguna. Ketika Anda tahu pengguna memiliki mouse, layar sentuh, dan keyboard - lalu apa? Menangani perilaku (pindah mouse, sentuh, keydown, dll). Pengguna dapat mengubah jenis input mereka pada "runtime", ini adalah masalah beasty nyata, ketika Anda sedang mengembangkan aplikasi nyata yang digunakan 8 hingga 5 tanpa memuat ulang.
Martin Lantzsch
2
+1 Secara pragmatis ini adalah jawaban terbaik untuk saya. Sebagai contoh, saya punya datagrid. Datagrid ini akan menampilkan "ikon edit" untuk disentuh untuk diedit atau menu konteks untuk opsi lainnya. Jika gerakan mouse terdeteksi, maka saya menghapus ikon (menghemat ruang di grid) dan pengguna dapat mengklik dua kali atau klik kanan.
Pemrogram
3
chrome on touch devices memicu mousemove sesekali
pstanton
9

Biola yang Bekerja

Saya telah mencapainya seperti ini;

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
sumber
tidak mendeteksi tablet permukaan windows
Dan Beaulieu
@DanBeaulieu bisa tolong spesifik ke perangkat, karena saya punya windows phone yang berfungsi dengan baik, juga saya telah menggunakannya dalam aplikasi saya yang QA: ED, saya akan memeriksa kembali lagi dan akan memperbarui jawabannya. Maaf atas ketidaknyamanan ini
Aamir Shahzad
Tidak yakin tahun berapa, itu adalah permukaan pro windows milik rekan kerja. Setelah menambahkan modernizr kami berhasil.
Dan Beaulieu
Ini melaporkan Non-Touch dengan benar pada mesin Windows 7 saya dan menyentuh pada Laptop Windows 8 dengan layar sentuh dan ponsel Android 4.4 MotoX.
Clay Nichols
Memberikan hasil positif palsu di Chrome (46) di Mac saya
Patrick Fabrizius
9

Ada sesuatu yang lebih baik daripada memeriksa apakah mereka memiliki layar sentuh, adalah memeriksa apakah mereka menggunakannya, plus itu lebih mudah untuk diperiksa.

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

Yang ini berfungsi dengan baik bahkan di 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");
}
}
Sathiyamoorthy
sumber
4

Saya menggunakan potongan-potongan kode di atas untuk mendeteksi apakah ada sentuhan, jadi iframe fancybox saya akan muncul di komputer desktop dan tidak di sentuh. Saya perhatikan bahwa Opera Mini untuk Android 4.0 masih mendaftar sebagai perangkat non-sentuh saat menggunakan kode blmstr saja. (Apakah ada yang tahu kenapa?)

Saya akhirnya menggunakan:

<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>
Dicintai
sumber
dapatkah Anda jelaskan, mengapa Anda tidak menggunakan satu panggilan pertandingan dengan satu regexp /iPhone|iPod|iPad|Android|BlackBerry/?
user907860
Opera Mini melakukan rendering pada server Opera dan bukan pada perangkat itu sendiri, jadi agak aneh.
bluesmoon
4

"Gotcha" terbesar dengan mencoba mendeteksi sentuhan ada pada perangkat hybrid yang mendukung sentuhan dan trackpad / mouse. Bahkan jika Anda dapat mendeteksi dengan benar apakah perangkat pengguna mendukung sentuhan, apa yang benar-benar perlu Anda lakukan adalah mendeteksi perangkat input apa yang saat ini digunakan pengguna. Ada tulisan rinci tentang tantangan ini dan kemungkinan solusi di sini .

Pada dasarnya pendekatan untuk mencari tahu apakah pengguna hanya menyentuh layar atau menggunakan mouse / trackpad sebagai gantinya adalah untuk mendaftarkan a touchstartdan mouseoveracara di halaman:

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

Tindakan sentuh akan memicu kedua peristiwa ini, meskipun yang pertama ( touchstart) selalu menjadi yang pertama di sebagian besar perangkat. Jadi mengandalkan urutan diprediksi peristiwa ini, Anda dapat membuat sebuah mekanisme yang secara dinamis menambahkan atau menghilangkan can-touchkelas ke akar dokumen untuk mencerminkan arus input type dari pengguna saat ini pada dokumen:

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

Lebih detail di sini .

kepulan coco
sumber
3

Lihat pos ini , ia memberikan potongan kode yang sangat bagus untuk apa yang harus dilakukan ketika perangkat sentuh terdeteksi atau apa yang harus dilakukan jika acara touchstart dipanggil:

$(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
sumber
3

Saya akan menghindari menggunakan lebar layar untuk menentukan apakah suatu perangkat adalah perangkat sentuh. Ada layar sentuh yang jauh lebih besar dari 699px, pikirkan Windows 8. Navigatior.userAgent mungkin bagus untuk mengesampingkan postur palsu.

Saya akan merekomendasikan untuk memeriksa masalah ini di Modernizr.

Apakah Anda ingin menguji apakah perangkat mendukung acara sentuh atau perangkat sentuh. Sayangnya, itu bukan hal yang sama.

hibrida
sumber
3

Tidak, itu tidak mungkin. Jawaban luar biasa yang diberikan hanya bersifat parsial, karena setiap metode yang diberikan akan menghasilkan positif palsu dan negatif palsu. Bahkan browser tidak selalu tahu apakah ada layar sentuh, karena API OS, dan fakta dapat berubah selama sesi browser, terutama dengan pengaturan tipe KVM.

Lihat detail lebih lanjut dalam artikel yang luar biasa ini:

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

Artikel tersebut menyarankan Anda untuk mempertimbangkan kembali asumsi yang membuat Anda ingin mendeteksi layar sentuh, mereka mungkin salah. (Saya memeriksa aplikasi saya sendiri, dan asumsi saya memang salah!)

Artikel itu menyimpulkan:

Untuk tata letak, anggap setiap orang memiliki layar sentuh. Pengguna mouse dapat menggunakan kontrol UI besar lebih mudah daripada pengguna sentuh dapat menggunakan kontrol kecil. Hal yang sama berlaku untuk negara melayang.

Untuk acara dan interaksi, anggap siapa pun mungkin memiliki layar sentuh. Terapkan interaksi keyboard, mouse, dan sentuh satu sama lain, memastikan tidak ada yang menghalangi satu sama lain.

Dave Burt
sumber
3

Banyak dari ini bekerja tetapi membutuhkan jQuery, atau javascript linters mengeluh tentang sintaks. Mempertimbangkan pertanyaan awal Anda meminta cara "JavaScript" (bukan jQuery, bukan Modernizr) untuk menyelesaikan masalah ini, inilah fungsi sederhana yang berfungsi setiap saat. Ini juga seminimal mungkin.

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

console.log(isTouchDevice());

Satu manfaat terakhir yang akan saya sebutkan adalah bahwa kode ini adalah framework dan perangkat agnostik. Nikmati!

seanforyou23
sumber
function isTouchScreen() { return window.matchMedia('(hover: none)').matches;}Ini bekerja untuk saya, jadi saya di sini menambahkan kontribusi untuk jawaban ini, karena saya juga mengharapkan thread JS vanilla ketika Google membawa saya ke sini.
Daniel Lavedonio de Lima
2

Sepertinya Chrome 24 sekarang mendukung acara sentuh, mungkin untuk Windows 8. Jadi kode yang diposting di sini tidak lagi berfungsi. Alih-alih mencoba mendeteksi apakah sentuhan didukung oleh browser, saya sekarang mengikat acara sentuh dan klik dan memastikan hanya satu yang disebut:

myCustomBind = function(controlName, callback) {

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

    callback.call();
  });
};

Dan kemudian menyebutnya:

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

Semoga ini membantu !

ahli sihir
sumber
2

Semua browser yang didukung kecuali Firefox untuk desktop selalu BENAR karena Firefox untuk desktop mendukung desain responsif untuk pengembang bahkan Anda mengklik Tombol Sentuh atau tidak!

Saya harap Mozilla akan memperbaiki ini di versi berikutnya.

Saya menggunakan desktop Firefox 28.

function isTouch()
{
    return !!("ontouchstart" in window) || !!(navigator.msMaxTouchPoints);
}
xicooc
sumber
ini masih versi 32.0 dan mereka belum memperbaikinya! gila. mengapa ini tidak bisa diubah? Ini selalu mengembalikan true:(
vsync
2

jQuery v1.11.3

Ada banyak informasi bagus dalam jawaban yang diberikan. Tapi, baru-baru ini saya menghabiskan banyak waktu mencoba untuk benar-benar mengikat semuanya menjadi solusi untuk dua hal:

  1. Mendeteksi bahwa perangkat yang digunakan adalah perangkat jenis layar sentuh.
  2. Mendeteksi bahwa perangkat disadap.

Selain posting ini dan Mendeteksi perangkat layar sentuh dengan Javascript , saya menemukan posting ini oleh Patrick Lauke sangat membantu: https://hacks.mozilla.org/2013/04/detecting-touch-its-the-why-not-the-how /

Ini kodenya ...

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

Penting! Itu*.on( events [, selector ] [, data ], handler ) Metode kebutuhan untuk memiliki pemilih, biasanya unsur, yang dapat menangani "touchstart" acara, atau lainnya seperti acara berhubungan dengan sentuhan. Dalam hal ini, itu adalah elemen hyperlink "a".

Sekarang, Anda tidak perlu menangani mengklik mouse biasa dalam JavaScript, karena Anda dapat menggunakan CSS untuk menangani peristiwa ini menggunakan penyeleksi untuk hyperlink "a" elemen seperti:

/* unvisited link */
a:link 
{

}

/* visited link */
a:visited 
{

}

/* mouse over link */
a:hover 
{

}

/* selected link */
a:active 
{

}

Catatan: Ada juga penyeleksi lainnya ...

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

atau

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

akan menjadi pemeriksaan yang lebih menyeluruh kurasa.

samuel segal
sumber
3
Akan lebih baik untuk dicatat yang uamengacu pada navigator.userAgent. Juga deteksi dengan lebar layar dapat memberikan hasil yang salah jika seseorang membuka browser dalam mode tidak layar penuh.
HoLyVieR
1

Saya menggunakan:

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

di jQuery mobile 1.0.1

Menandai
sumber
1

Saya juga banyak kesulitan dengan berbagai opsi tentang cara mendeteksi dalam Javascript apakah halaman ditampilkan pada perangkat layar sentuh atau tidak. IMO, sampai sekarang, tidak ada opsi nyata untuk mendeteksi opsi dengan benar. Peramban melaporkan acara sentuh pada mesin desktop (karena OS mungkin siap sentuh), atau beberapa solusi tidak berfungsi pada semua perangkat seluler.

Pada akhirnya, saya menyadari bahwa saya mengikuti pendekatan yang salah sejak awal: Jika halaman saya terlihat serupa pada perangkat sentuh dan non-sentuh, saya mungkin tidak perlu khawatir tentang mendeteksi properti sama sekali: Skenario saya adalah untuk menonaktifkan tooltips di atas tombol pada perangkat sentuh saat mereka mengarah ke ketukan ganda di mana saya ingin satu ketukan untuk mengaktifkan tombol.

Solusi saya adalah untuk refactor pandangan sehingga tidak ada keterangan alat yang dibutuhkan lebih tombol, dan pada akhirnya saya tidak perlu mendeteksi perangkat sentuh dari Javascript dengan metode yang semua memiliki kelemahan mereka .

Michael
sumber
1

Anda dapat menginstal modernizer dan menggunakan acara sentuh sederhana. Ini sangat efektif dan berfungsi pada setiap perangkat yang telah saya uji termasuk pada permukaan windows!

Saya telah membuat 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
sumber
3
Selamat datang di SO! Kode dengan sendirinya (seperti kode uncommented) jarang merupakan jawaban. Anda dapat meningkatkan jawaban ini dengan menambahkan penjelasan cuplikan.
ebarr
1

Jawaban praktisnya tampaknya adalah yang mempertimbangkan konteks:

1) Situs publik (tanpa login)
Kode UI untuk bekerja dengan kedua opsi bersama-sama.

2) Situs login
Tangkap apakah mouse-move terjadi pada formulir login, dan simpan ini ke input tersembunyi. Nilai dilewatkan dengan kredensial masuk dan ditambahkan ke sesi pengguna , sehingga dapat digunakan selama durasi sesi.

Jquery untuk ditambahkan ke halaman login saja:

$('#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 ke @Dave Burt dan +1 ke @Martin Lantzsch pada jawaban mereka)

prograhammer
sumber
1

Masalah

Karena perangkat hybrid yang menggunakan kombinasi input sentuhan dan mouse, Anda harus dapat secara dinamis mengubah status / variabel yang mengontrol apakah sepotong kode harus dijalankan jika pengguna adalah pengguna sentuh atau tidak.

Perangkat sentuh juga mengaktifkan mousemoveketukan.

Larutan

  1. Anggap sentuhan itu salah saat memuat.
  2. Tunggu hingga sebuah touchstartacara dipecat, lalu setel ke true.
  3. Jika touchstart dipecat, tambahkan handler mousemove.
  4. Jika waktu antara dua peristiwa mousemove menembak kurang dari 20 ms, anggap mereka menggunakan mouse sebagai input. Hapus acara karena tidak lagi diperlukan dan mouse adalah acara mahal untuk perangkat mouse.
  5. Segera setelah touchstart diaktifkan kembali (pengguna kembali menggunakan sentuhan), variabel tersebut disetel kembali ke true. Dan ulangi prosesnya sehingga ditentukan secara dinamis. Jika dengan suatu keajaiban mousemove dipecat dua kali pada sentuhan bukan kepalang cepat (dalam pengujian saya itu hampir mustahil untuk melakukannya dalam 20ms), touchstart berikutnya akan mengaturnya kembali ke true.

Diuji pada Safari iOS dan Chrome untuk Android.

Catatan: tidak 100% yakin pada pointer-events untuk MS Surface, dll.

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);
}
sangat dingin
sumber
1

Sebenarnya, saya meneliti pertanyaan ini dan mempertimbangkan semua situasi. karena itu adalah masalah besar pada proyek saya juga. Jadi saya mencapai fungsi di bawah ini, ini berfungsi untuk semua versi dari semua browser di semua perangkat:

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

Petunjuk : Jelas,isTouchDevicejust mengembalikanbooleannilai.

Amerika
sumber
0

supportObjek jQuery yang diperluas :

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

Dan sekarang Anda dapat memeriksanya di mana saja, seperti ini:

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

Sejauh ini ini sepertinya bekerja dengan baik untuk saya:

//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
sumber
0

Ketika mouse terpasang, dapat diasumsikan dengan hitrate cukup tinggi (saya akan mengatakan hampir 100%) bahwa pengguna menggerakkan mouse setidaknya jarak kecil setelah halaman siap - tanpa mengklik. Mekanisme di bawah mendeteksi ini. Jika terdeteksi, saya menganggap ini sebagai tanda dukungan sentuh yang hilang atau, jika didukung, kurang penting ketika mouse sedang digunakan. Perangkat sentuh diasumsikan jika tidak terdeteksi.

EDIT Pendekatan ini mungkin tidak cocok untuk semua tujuan. Ini dapat digunakan untuk mengontrol fungsionalitas yang diaktifkan berdasarkan interaksi pengguna pada halaman yang dimuat, misalnya penampil gambar. Kode di bawah ini juga akan membuat acara mousemove terikat pada perangkat tanpa mouse seperti yang terlihat sekarang. Pendekatan lain mungkin lebih baik.

Secara kasar, bunyinya seperti ini (maaf untuk jQuery, tetapi serupa dengan Javascript murni):

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
sumber