JavaScript kullanarak bir 'dokunmatik ekran' cihazı tespit etmenin en iyi yolu nedir?


416

Hem masaüstü hem de mobil cihazlarda kullanım için bir jQuery eklentisi yazdım. JavaScript ile cihazın dokunmatik ekran özelliğine sahip olup olmadığını tespit etmenin bir yolu olup olmadığını merak ettim. Dokunmatik ekran olaylarını tespit etmek için jquery-mobile.js kullanıyorum ve iOS, Android vb.

Mümkün mü?


bu, document.documentElement öğesindeki var x = 'touchstart' öğesinin daha iyi bir yoludur; console.log (x) // destekleniyorsa true
döndür

Hala yeni teknikler ortaya çıkmaya devam ediyorsa , bu iplik neden korunuyor ?
Andy Hoffman

Yanıtlar:


139

Güncelleme: Tüm özellik algılama kitaplığını projenize çekmeden önce lütfen aşağıdaki blmstr yanıtını okuyun . Gerçek dokunma desteğini tespit etmek daha karmaşıktır ve Modernizr yalnızca temel bir kullanım durumunu kapsar.

Modernizr , herhangi bir sitede her türlü özellik tespiti yapmanın harika ve hafif bir yoludur.

Her özellik için html öğesine sınıflar ekler.

Daha sonra bu özellikleri CSS ve JS'de kolayca hedefleyebilirsiniz. Örneğin:

html.touch div {
    width: 480px;
}

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

Ve Javascript (jQuery örneği):

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

88
Modernizr dokunmatik ekranları test etmez. Tarayıcıda dokunma olaylarının varlığını test eder. Dokümanlardaki "Çeşitli Testler" bölümüne bakın: modernizr.com/docs/#features-misc
Harry Love

1
(Modernizr.touch) {/ * dokunma şeyleri yapın /} başka {/ iyi, yapma * /} ise, Touch olaylarının varlığı için bir JS testi de yapabilirsiniz
Anatoly G

7
@ Harrylove'un noktasına gelince, Windows 8 çıktığı için Modernizr yanlış tüm PC tarayıcılarımı dokunmatik uyumlu olarak döndürüyor.
Anton

3
Güncelleme: blmstr cevabı daha iyidir ve saf bir Javascript çözümüdür.
Alan Christopher Thomas

1
Eğer Modernizr.touchbeklenmedik döner undefined, özelleştirilmiş bir Modernizr olabilir Dokunmatik Olay tespiti için desteği olmadan (eğer seçmeyi ve almak).
Henrik N

679

Bu işlevi kullanmayı denediniz mi? (Bu, Modernizr'ın kullandığı ile aynıdır.)

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

console.log(is_touch_device());

GÜNCELLEME 1

document.createEvent("TouchEvent")trueen son kromu kullanmaya başladı (v. 17). Modernizr bunu bir süre önce güncelledi. Modernizr testine buradan göz atın .

Çalışmasını sağlamak için işlevinizi şu şekilde güncelleyin:

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

console.log(is_touch_device1());

GÜNCELLEME 2

Yukarıdaki IE10 (MS Surface üzerinde false döndüren) üzerinde çalışma değildi bulundu. İşte düzeltme:

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

GÜNCELLEME 3

'onmsgesturechange' in windowgüvenilir değil bazı IE masaüstü sürümlerinde doğru dönecektir. Bu biraz daha güvenilir bir şekilde çalışır:

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

GÜNCELLEME 2018

Zaman geçiyor ve bunu test etmenin yeni ve daha iyi yolları var. Temelde Modernizr'in kontrol etme yöntemini çıkardım ve basitleştirdim:

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

Burada touch-enabledbiraz garip ve kötü bir uygulama olduğunu düşünüyorum standart olmayan medya sorgu özelliği kullanıyorlar . Ama hey, gerçek dünyada sanırım işe yarıyor. Gelecekte (herkes tarafından desteklendiklerinde) bu medya sorgusu özellikleri size aynı sonuçları verebilir: pointerve hover.

Check out Modernizr nasıl yapıyorlar kaynağını .

Dokunmatik algılama ile ilgili sorunları açıklayan iyi bir makale için bkz. Stu Cox: Bir Dokunmatik Ekranı Tespit Edemezsiniz .


20
Çift patlama, boole değerine bir değer atar ve işlevi ya trueda işlevini döndürmeye zorlar false. Bununla ilgili daha fazla bilgiyi buradan edinebilirsiniz: stackoverflow.com/questions/4686583/…
Rob Flaherty

2
Opera Mobile 10 veya Internet Explorer Mobile 6 (Windows Mobile 6.5) ile çalışmaz.
doubleJ

17
Çift NOT (!!), inoperatör zaten bir boole değerini değerlendirdiğinden gereksizdir .
Steve

11
'onmsgesturechange'dokunmatik olmayan cihazlarda (PC) bile doğru değerlendiriyor. window.navigator.msMaxTouchPointsdaha doğru görünüyor. Burada buldum .
Steve

6
Ekranımda dokunma sensörü olmamasına rağmen Windows 8'de IE10'da doğru olarak değerlendiriliyor. Eski dizüstü bilgisayarımı Windows 7'den Windows 8'e
yükselttim

120

Modernizr, Windows Phone 8 / WinRT'de IE10'u algılamadığından, basit bir çapraz tarayıcı çözümü:

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

Cihaz bir kez dokunmayı desteklemeyeceği veya desteklemeyeceği için yalnızca bir kez kontrol etmeniz gerekir, bu yüzden sadece bir değişkende saklayın, böylece birden çok kez daha verimli kullanabilirsiniz.


3
Penceredeki 'onmsgesturechange', dokunmatik olmayan cihazlarda "masaüstü" IE10'u da algılar, bu nedenle bu, dokunmayı belirlemek için güvenilir bir yöntem değildir.
Matt Stow

6
Bu cevap en iyi ve en basit ve güncel cevap olduğu için kabul edilmiş olmalıdır. Bir fonksiyonda bu daha tutarlı olacağını düşünüyorum: return !!('ontouchstart' in window) || !!('msmaxtouchpoints' in window.navigator);(her iki cevap birleştirmek için) IE10 da iyi çalışıyor!
Yeti

Bu kabul edilen cevap olmalı. 'onmsgesturechange' in windowdokunma mümkün olduğunda bile IE10 masaüstünde true döndürür
Sam Thornton

6
İhtiyacınız olan her şey:function isTouchDevice() { return 'ontouchstart' in window || !!(navigator.msMaxTouchPoints);}
GFoley83

1
Hatta GFoleys pencerede 'ontouchstart' önerisi || !! (navigator.msMaxTouchPoints); Chrome 30 dev 2014'te fals'ı pozitif olarak döndürdü.
Tom Andersen

37

Yukarıdaki tüm yorumları kullanarak benim ihtiyaçları için çalışan aşağıdaki kodu monte:

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

Bunu iPad, Android (Tarayıcı ve Chrome), Blackberry Playbook, iPhone 4s, Windows Phone 8, IE 10, IE 8, IE 10 (Dokunmatik Ekranlı Windows 8), Opera, Chrome ve Firefox'ta test ettim.

Şu anda Windows Phone 7'de başarısız oluyor ve henüz bu tarayıcı için bir çözüm bulamadım.

Umarım birisi bunu faydalı bulur.


Kullanamamanın herhangi bir nedeni var mı: function is_touch_device () {return !! (pencerede 'ontouchstart') || !! (gezginde 'msmaxtouchpoints'); };
sidonaldson

işlevini kullanmak işe yarayacaktır ama genellikle yukarıdaki değişken yöntemini kullanmak istiyorum, bu yüzden sadece bir kez test edilir ve daha sonra kodumda kontrol ettiğimde daha hızlıdır. Ayrıca msMaxTouchPoints, Windows 8'de IE 10 olarak 0'dan fazla olup olmadığını test etmek için gerekli olduğunu gördüm, dokunmatik ekran olmadan 0 msMaxTouchPoints olarak 0 döndürüyordu.
David

trueWindows 7'de Firefox 32
cihazımı

Windows 8'deki Firefox 33 ve 33.1, ikisi de sistemimde yanlış gösteriyor. Firefox'unuzu en son sürüme yükseltirseniz, yine de doğru mu dönüyor? Makinenizde, Firefox'un makinenizin dokunduğunu yanlış düşünmesini sağlayacak bir cihaz yüklü olabilir mi?
David

Pencerede >>> 'ontouchstart' >>> ubuntu üzerinde gerçek FF 51.0.1
Ravi

25

Etkileşim ortamı özelliklerinin tanıtımından bu yana şunları yapabilirsiniz:

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

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

Güncelleme (yorumlardan dolayı): Yukarıdaki çözüm, bir "kaba işaretçi" nin (genellikle bir dokunmatik ekran) birincil giriş cihazı olup olmadığını tespit etmektir. Fare gibi bir aygıtın dokunmatik ekranı olup olmadığını tespit etmek istiyorsanız, any-pointer: coarsebunun yerine kullanabilirsiniz .

Daha fazla bilgi için buraya bir göz atın: Tarayıcının fare olmadığını ve yalnızca dokunmatik olduğunu algılama


3
Bu açık ara en iyi çözüm, teşekkürler! Her ne kadar (pointer: coarse)büyük olasılıkla sadece birincil girdiyi hedeflediğinizi kullanmanızı öneririm . Desteklenmeyen birkaç tarayıcı yalnızca masaüstü olduğu için üretimde kullanılabilir. Bu konuda css-hileler hakkında harika bir makale var .
Fabian von Ellerts

2
Test ettiğim her durumda çalışan tek çözüm budur. Teşekkürler!
kaiserkiwi

20

Bunu beğendim:

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

alert(isTouchDevice());

12
Bir boole döndürmek için üçlü bir ifade kullanmaya gerek yoktur. Boole değerini döndürmek için ifadeyi kullanmanız yeterlidir. function isTouchDevice(){ return (window.ontouchstart !== undefined); }
Tim Vermaelen

1
Ayrıca şunları da kullanabilirsiniz: var isTouch = 'ontouchstart' in window;ancak bu en son Chrome (v31) ile çalışmaz var isTouch = 'createTouch' in window.document;, hala çalışıyor.
Olivier

2
Daha önce de kabul edilen sorunun yorumlarında belirtildiği gibi. "Modernizr dokunmatik ekranları test etmez. Tarayıcıda dokunma olaylarının varlığını test eder". Fonksiyonunuz teknik olarak hasTouchEvents () değil isTouchDevice ()
hexalys

Benzer yöntemler testinin touchstart, IE'nin pointerolayları kullandığı için Surface'i bir dokunmatik cihaz olarak tanıyamayacağını unutmayın .
CookieMonster

1
Belki @Nis haklıydı, ancak Firefox 39'da doğru şekilde yanlış döndürüyor.
Dan Dascalescu

17

Eğer kullanırsanız Modernizr , çok kolay kullanmaktır Modernizr.touchönce belirtildiği gibi.

Ancak, Modernizr.touchsadece güvenli olmak için bir kombinasyon ve kullanıcı aracısı testi kullanmayı tercih ederim .

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
    }

Modernizr kullanmıyorsanız, Modernizr.touchyukarıdaki işlevi basitçe('ontouchstart' in document.documentElement)

Ayrıca, kullanıcı aracısını test etmenin iemobile, size tespit edilen Microsoft mobil cihazlarından daha geniş bir aralık sunacağını unutmayın Windows Phone.

Ayrıca bu SO sorusuna bakın


8
"Dokunaklı bir şey yap" ve "buna dokunamaz" için bir sürü bonus puanı
Lee Saxon

aynı cihazlar için birden çok kez kontrol edersiniz ve yalnızca birini kullanabildiğinizde birden çok Normal İfade yaparsınız. artı, büyük / küçük harfe duyarsız regex'ler yapıyorsunuz ancak dize zaten küçük harflerle yazılmış.
caesarsol

1
Bu yeterli olmalı:/(iphone|ipod|ipad|android|iemobile|blackberry|bada)/.test(window.navigator.userAgent.toLowerCase())
Caesarsol

Eşleşen büyük / küçük harfe duyarlı olmamak için herhangi bir neden var mı? "İOS", "Android" veya "IEMobile" diğer kasaları ne zaman kullanır?
Henrik N

14

Modernizr uygulamasını denedik, ancak dokunma olaylarını tespit etmek artık tutarlı değil (IE 10'un Windows masaüstünde dokunma olayları var, IE 11 çalışıyor, çünkü dokunma olaylarını düşürdüm ve işaretçi api ekledim).

Bu nedenle, kullanıcının hangi giriş türüne sahip olduğunu bilmediğimiz sürece web sitesini bir dokunmatik site olarak optimize etmeye karar verdik. Bu, diğer tüm çözümlerden daha güvenilirdir.

Araştırmalarımız, çoğu masaüstü kullanıcısının fare ile tıklamadan önce ekran üzerinde hareket ettiğini söylüyor, böylece herhangi bir şeyi tıklayamadan veya üzerine gelmeden önce bunları tespit edebiliyor ve davranışı değiştirebiliyoruz.

Bu, kodumuzun basitleştirilmiş bir sürümüdür:

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

bugün bilgisayarların hem dokunmatik hem de faresi var ... farklılaştırmalısınız. sadece dokunma, fare veya her ikisinin de olup olmadığını bilmek için mutlak bir zorunluluktur. 3 farklı eyalet.
vsync

1
Evet haklısın, ama bu çok zor. En iyi durumda, uygulamanız herhangi bir giriş denetleyicisi tarafından kullanılmak üzere tasarlanmıştır ve kullanıcının dokunmatik ekranı, faresi, klavyesi veya hepsi birlikte olup olmadığı önemli değildir.
Martin Lantzsch

1
Kullanıcının davranışı, kullanıcının ne tür bir cihaza sahip olduğuna dair gerçek bilgilerden daha değerlidir. Kullanıcının bir faresi, dokunmatik ekranı ve klavyesi olduğunu bildiğinizde ne olur? Davranışı yönetin (fareyle üzerine gelme, dokunma hareketi, tuş kilidi vb.). Kullanıcılar "çalışma zamanında" giriş türlerini değiştirebilirler, bu yeniden yükleme olmadan 8 ila 5 kullanılan gerçek bir uygulama geliştirirken, gerçek bir canavar sorunudur.
Martin Lantzsch

2
+1 Pragmatik olarak bu benim için en iyi cevap. Örneğin, veri ızgaralarım var. Bu veri ızgaralarında düzenleme için dokunmak üzere bir "düzenleme simgesi" veya daha fazla seçenek için bir bağlam menüsü gösterilir. Fare hareketi algılanırsa, simgeyi kaldırırım (ızgarada yer kazandırır) ve kullanıcılar çift tıklatabilir veya sağ tıklatabilir.
prograhammer

3
dokunmatik cihazlarda krom ara sıra
fareyi harekete geçirir

9

Çalışma keman

Ben böyle başardım;

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
}

Windows yüzey tableti algılamıyor
Dan Beaulieu

@DanBeaulieu lütfen cihaza özgü olabilir, çünkü onun iyi çalışıyor için windows telefon var, ayrıca QA: ED olan uygulamamda kullandım, tekrar kontrol edeceğim ve cevabı güncelleyeceğim. Rahatsızlık için özür dilerim
Aamir Shahzad

Hangi yıl emin değilim, bu bir iş arkadaşına ait bir windows surface pro. Modernizr ekledikten sonra işe koyulduk.
Dan Beaulieu

Bu, Windows 7 makinemde Dokunmama durumunu ve dokunmatik ekranlı bir Windows 8 Dizüstü Bilgisayar ve Android 4.4 MotoX telefonuna dokunmayı doğru şekilde bildirdi.
Clay Nichols

Mac bilgisayarımda Chrome'da (46) yanlış pozitif
veriyor

9

Bir touchScreen'e sahip olup olmadıklarını kontrol etmekten daha iyi bir şey var, kullanılıp kullanılmadıklarını kontrol etmektir, ayrıca kontrol edilmesi daha kolaydır.

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

6

Bu Windows Yüzey tabletlerinde bile iyi çalışır !!!

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

Dokunma olup olmadığını tespit etmek için yukarıdaki kodun parçalarını kullandım, bu yüzden fancybox iframe'leri dokunmatik bilgisayarlarda değil masaüstü bilgisayarlarda görünecekti. Android 4.0 için Opera Mini'nin yalnızca blmstr kodunu kullanırken hala dokunmatik olmayan bir cihaz olarak kaydedildiğini fark ettim. (Nedenini bilen var mı?)

Ben kullanarak sona erdi:

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

açıklayabilir misiniz, neden tek bir regexp ile tek bir eşleşme çağrısı kullanmıyorsunuz /iPhone|iPod|iPad|Android|BlackBerry/?
user907860

Opera Mini, cihazın kendisinde değil Opera'nın sunucularında oluşturmayı gerçekleştirdiğinden, bu şekilde biraz garip.
bluesmoon

4

Dokunmayı algılamaya çalışan en büyük "gotcha", hem dokunmayı hem de izleme dörtgenini / fareyi destekleyen hibrit cihazlarda. Kullanıcının cihazının dokunmayı destekleyip desteklemediğini doğru bir şekilde tespit edebilseniz bile, gerçekten yapmanız gereken kullanıcının şu anda hangi giriş cihazını kullandığını tespit etmektir . Bu zorluğun ayrıntılı bir yazımı ve burada olası bir çözüm var .

Bir kullanıcı sadece ekranı dokundu veya bir fare / dokunmatik yerine a hem kayıt olup kullanılan yetip için Temelde yaklaşım touchstartve mouseoversayfasından etkinliğe:

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

Dokunma eylemi bu olayların her ikisini de tetikleyecektir, ancak eski ( touchstart) her zaman çoğu cihazda ilk sıradadır. Bu öngörülebilir olay dizisine güvenerek , kullanıcının şu anda belgedeki geçerli giriş türünü can-touchyansıtmak için belge köküne dinamik olarak bir sınıf ekleyen veya kaldıran bir mekanizma oluşturabilirsiniz :

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

Daha fazla ayrıntı burada .


3

Şuna bak yazı , bu touchstart olay denir, yapmanız dokunmatik cihazlar algılandığında yapmak ya da ne ne için gerçekten güzel bir kod parçası verecektir:

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

Bir aygıtın dokunmatik aygıt olup olmadığını belirlemek için ekran genişliğini kullanmaktan kaçınırım. 699 pikselden çok daha büyük dokunmatik ekranlar var, Windows 8'i düşünün. Navigatior.userAgent yanlış duruşları geçersiz kılmak için güzel olabilir.

Modernizr bu sorunu kontrol etmenizi tavsiye ederim .

Cihazın dokunma olaylarını destekleyip desteklemediğini veya bir dokunmatik cihaz olup olmadığını test etmek mi istiyorsunuz? Ne yazık ki, bu aynı şey değil.


3

Hayır, bu mümkün değil. Verilen mükemmel cevaplar sadece kısmi, çünkü verilen herhangi bir yöntem yanlış pozitif ve yanlış negatif üretecektir. Tarayıcı bile, işletim sistemi API'ları nedeniyle bir dokunmatik ekranın olup olmadığını her zaman bilmez ve bir tarayıcı oturumu sırasında, özellikle de KVM tipi düzenlemelerle, gerçek değişebilir.

Bu mükemmel makaledeki diğer ayrıntılara bakın:

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

Makale, dokunmatik ekranları algılamanızı isteyen varsayımları yeniden gözden geçirmenizi önerir, muhtemelen yanlıştır. (Uygulamam için kendimi kontrol ettim ve varsayımlarım gerçekten yanlıştı!)

Makale şu sonuca varıyor:

Düzenler için herkesin dokunmatik ekranı olduğunu varsayın. Fare kullanıcıları, büyük UI denetimlerini dokunmatik kullanıcıların küçük olanları kullanabileceğinden çok daha kolay kullanabilir. Aynı durum fareyle üzerine gelme durumları için de geçerlidir.

Etkinlikler ve etkileşimler için, herhangi birinin dokunmatik ekrana sahip olabileceğini varsayın. Klavye, fare ve dokunma etkileşimlerini yan yana getirerek hiçbirinin birbirini engellememesini sağlayın.


3

Bu çalışmaların çoğu jQuery gerektirir veya javascript linters sözdiziminden şikayet eder. İlk sorunuz, bunu çözmenin bir "JavaScript" (jQuery değil, Modernizr değil) yolunu düşündüğünüzde, her seferinde çalışan basit bir işlev. Ayrıca alabildiğiniz kadar az.

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

console.log(isTouchDevice());

Bahseteceğim son bir fayda, bu kodun çerçeve ve cihaz agnostik olmasıdır. Zevk almak!


function isTouchScreen() { return window.matchMedia('(hover: none)').matches;}Bu benim için çalıştı, bu yüzden bu yanıta bir katkı ekliyorum, çünkü Google beni buraya getirdiğinde vanilya JS iş parçacığını da bekliyordum.
Daniel Lavedonio de Lima

2

Görünüşe göre Chrome 24, muhtemelen Windows 8 için dokunma olaylarını destekliyor gibi. Bu nedenle, burada yayınlanan kod artık çalışmıyor. Dokunmanın tarayıcı tarafından desteklenip desteklenmediğini algılamak yerine, artık hem dokunma hem de tıklama olaylarını bağlayıp yalnızca bir tanesinin çağrıldığından emin oluyorum:

myCustomBind = function(controlName, callback) {

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

    callback.call();
  });
};

Sonra çağırıyoruz:

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

Bu yardımcı olur umarım !



2

Masaüstü için Firefox dışında desteklenen tüm tarayıcılar, Touch-Button'ı tıklasanız da tıklamasanız bile, masaüstü için Firefox desteği geliştirici için duyarlı tasarımı nedeniyle her zaman DOĞRU !

Umarım Mozilla bunu bir sonraki sürümde düzeltir.

Firefox 28 masaüstünü kullanıyorum.

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

hala 32.0 sürümü ve henüz düzeltmediler! deli. neden bu değiştirilemez ?? Bu her zaman şunu döndürür true:(
vsync

2

jQuery v1.11.3

Verilen cevaplarda birçok iyi bilgi var. Ama son zamanlarda, her şeyi başarmak için her şeyi çalışan bir çözüme bağlamak için çok zaman harcadım:

  1. Kullanılan cihazın bir dokunmatik ekran tipi cihaz olduğunu tespit edin.
  2. Cihazın hafifçe vurulduğunu tespit edin.

Bu yazının ve Javascript ile dokunmatik ekran cihazlarının yanı sıra , Patrick Lauke'nin bu yazısını son derece yararlı buldum: https://hacks.mozilla.org/2013/04/detecting-touch-its-the-why-not-the-how /

İşte kod ...

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

Önemli! *.on( events [, selector ] [, data ], handler )Yöntem ihtiyacı "touchstart" etkinliği ya da dokunur ilişkili olay gibi başka işleyebilir bir seçici, genellikle bir öğe, var. Bu durumda, "a" köprü elemanıdır.

Şimdi, JavaScript'te normal fare tıklatmasıyla uğraşmanıza gerek yok, çünkü aşağıdaki gibi "a" öğesi köprüsü için seçicileri kullanarak bu olayları işlemek için CSS kullanabilirsiniz:

/* unvisited link */
a:link 
{

}

/* visited link */
a:visited 
{

}

/* mouse over link */
a:hover 
{

}

/* selected link */
a:active 
{

}

Not: Başka seçiciler de var ...


1
var isTouchScreen = 'createTouch' in document;

veya

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

sanırım daha kapsamlı bir kontrol olurdu.


3
Bunu belirtmek iyi uaolur navigator.userAgent. Ayrıca, bir kişi tam ekran modunda değilken bir tarayıcı açarsa ekran genişliğine göre algılama yanlış sonuç verebilir.
HoLyVieR

1

Kullanırım:

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

jQuery mobile 1.0.1 içinde


1

Ayrıca, sayfanın bir dokunmatik ekran cihazında görüntülenip görüntülenmediğini Javascript'te nasıl algılayacağımız konusunda farklı seçeneklerle çok uğraştım. IMO, şu an için, seçeneği doğru bir şekilde tespit etmek için gerçek bir seçenek yok. Tarayıcılar, masaüstü makinelerde dokunma olaylarını bildirir (çünkü işletim sistemi dokunmaya hazır olabilir) veya bazı çözümler tüm mobil cihazlarda çalışmaz.

Sonunda, en başından itibaren yanlış yaklaşımı izlediğimi fark ettim: Sayfam dokunmatik ve dokunmatik olmayan cihazlarda benzer görünecek olsaydı, belki de mülkü tespit etme konusunda endişelenmemeliydim: Senaryom şuydu: düğmeyi etkinleştirmek için tek bir dokunuş olmasını istediğim çift dokunuşlara yol açtıklarından, dokunmatik cihazlardaki düğmelerin üzerindeki araç ipuçlarını devre dışı bırakmak için.

Benim çözümüm bir düğme üzerinde hiçbir araç ipucu gerekli böylece görünümü yeniden , ve sonunda tüm dezavantajları olan yöntemler ile Javascript dokunmatik cihazı tespit etmek gerek yoktu .


1

Modernizatörü kurabilir ve basit bir dokunma olayı kullanabilirsiniz. Bu çok etkilidir ve Windows yüzeyi dahil olmak üzere test ettiğim her cihazda çalışır!

Bir jsFiddle oluşturdum

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
SO hoş geldiniz! Kod tek başına (önerilmeyen kod gibi) nadiren bir cevap oluşturur. Parçacığın bir açıklamasını ekleyerek bu yanıtı geliştirebilirsiniz.
ebarr

1

Pratik cevap, bağlamı dikkate alan bir cevap gibi görünmektedir:

1) Genel site (giriş yok)
Kullanıcı arayüzünü her iki seçenekle birlikte çalışacak şekilde kodlayın.

2) Oturum açma sitesi
Oturum açma formunda fare hareketinin olup olmadığını yakalayın ve bunu gizli bir girişe kaydedin. Değer, oturum açma kimlik bilgileriyle iletilir ve kullanıcının oturumuna eklenir , böylece oturum süresince kullanılabilir.

Sadece giriş sayfasına eklemek için jquery:

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

(Cevaplarında +1Dave Burt'a ve +1Martin Lantzsch'a +1)


1

Sorun

Dokunma ve fare girişinin bir kombinasyonunu kullanan karma cihazlar nedeniyle , kullanıcının bir dokunma kullanıcısı olup olmadığı konusunda bir kod parçasının çalıştırılıp çalıştırılmayacağını kontrol eden durumu / değişkeni dinamik olarak değiştirebilmeniz gerekir.

Dokunmatik cihazlar da mousemovemuslukta ateş ediyor.

Çözüm

  1. Yükte dokunmanın yanlış olduğunu varsayın.
  2. Bir touchstartolay tetiklenene kadar bekleyin , ardından doğru olarak ayarlayın.
  3. Touchstart tetiklendiyse, bir fareyle üzerine gelme işleyicisi ekleyin.
  4. Ateşleme sırasında iki fareyle taşınan olay arasındaki süre 20 ms'den azsa, giriş olarak bir fare kullandıklarını varsayın. Etkinliği artık gerekmediğinden kaldırın ve fareyle üzerine gelme fare aygıtları için pahalı bir olaydır.
  5. Touchstart tekrar başlatıldığında (kullanıcı dokunma işlevine geri döndü), değişken tekrar true değerine ayarlanır. Ve işlemi tekrarlayın, böylece dinamik bir şekilde belirlenir. Bazı mucize mousemove dokunarak iki kez saçma sapan hızlı bir şekilde ateşlenirse (testlerimde 20ms içinde yapmak neredeyse imkansız), bir sonraki dokunmatik başlangıç ​​tekrar doğruya dönecektir.

Android için Safari iOS ve Chrome'da test edildi.

Not: MS Surface, vb için işaretçi olaylarında% 100 emin değilim.

Codepen demosu


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

Aslında, bu soruyu araştırdım ve tüm durumları ele aldım. çünkü bu benim projemde de büyük bir sorun. Bu yüzden aşağıdaki fonksiyona ulaşıyorum, tüm cihazlardaki tüm tarayıcıların tüm sürümleri için çalışıyor:

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

İpucu : Kesinlikle,isTouchDevicesadecebooleandeğerleridöndürür.


0

JQuery supportnesnesini genişlet :

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

Ve şimdi herhangi bir yerde kontrol edebilirsiniz, şöyle:

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

0

Bu benim için şimdiye kadar iyi çalışıyor gibi görünüyor:

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

Bir fare takıldığında, kullanıcının fareyi sayfa hazır olduktan sonra en az küçük bir mesafeyi herhangi bir tıklama yapmadan hareket ettirdiği oldukça yüksek bir hitrate (pratik olarak% 100 diyebilirim) varsayılabilir. Aşağıdaki mekanizma bunu tespit eder. Tespit edilirse, bunu eksik dokunmatik desteğin bir işareti olarak veya destekleniyorsa, bir fare kullanılırken önemsiz olarak görüyorum. Dokunmatik cihaz algılanmazsa varsayılır.

DÜZENLE Bu yaklaşım her amaca uygun olmayabilir. Yüklenen sayfadaki kullanıcı etkileşimi, örneğin bir resim görüntüleyici temelinde etkinleştirilen işlevselliği kontrol etmek için kullanılabilir. Aşağıdaki kod, fareyle üzerine gelme olayını, şimdi göze çarptığı için faresiz cihazlara bağlı bırakacaktır. Diğer yaklaşımlar daha iyi olabilir.

Kabaca, şu şekilde gider (jQuery için özür dilerim, ancak saf Javascript'te benzer):

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;
}));
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.