Який найкращий спосіб виявити пристрій "сенсорний екран" за допомогою JavaScript?


416

Я написав плагін jQuery, який використовується для настільних і мобільних пристроїв. Мені було цікаво, чи існує спосіб з JavaScript визначити, чи має пристрій можливість сенсорного екрана. Я використовую jquery-mobile.js для виявлення подій сенсорного екрану, і він працює на iOS, Android тощо, але я також хотів би написати умовні заяви на основі того, чи має у пристрою користувача сенсорний екран.

Це можливо?


це кращий спосіб var x = 'touchstart' у document.documentElement; console.log (x) // повернути true, якщо підтримується // else return false
Risa__B

Чому ця нитка захищена, якщо нові методи все ще з'являються?
Енді Гофман

Відповіді:


139

Оновлення. Будь ласка, прочитайте відповідь blmstr нижче, перш ніж втягнути в проект цілу бібліотеку виявлення функцій. Виявлення фактичної підтримки дотику складніше, і Modernizr охоплює лише базовий випадок використання.

Modernizr - це чудовий, легкий спосіб робити всі види виявлення функцій на будь-якому сайті.

Він просто додає класи до елемента html для кожної функції.

Потім ви можете легко націлити ці функції на CSS та JS. Наприклад:

html.touch div {
    width: 480px;
}

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

І Javascript (приклад jQuery):

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

88
Modernizr не тестує на сенсорні екрани. Він перевіряє наявність сенсорних подій у браузері. Дивіться розділ "Різні тести" в документах: modernizr.com/docs/#features-misc
Гаррі Лав

1
Ви також можете зробити тест JS на наявність подій на дотик, якщо (Modernizr.touch) {/ * do touch речі /} else {/ штрафуйте, не * /}
Анатолій Г

7
До точки зору @ harrylove, після виходу Windows 8, Modernizr неправильно повертав усі браузери мого ПК як сумісні з сенсорним доступом.
Антон

3
Оновлення: відповідь blmstr краще, і це чисте рішення Javascript.
Алан Крістофер Томас,

1
Якщо Modernizr.touchнесподівано повернеться undefined, у вас може бути налаштований Modernizr (ви можете вибрати і вибрати) без підтримки виявлення сенсорних подій.
Генрік N

679

Ви спробували скористатися цією функцією? (Це те саме, що раніше використовував Modernizr.)

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

console.log(is_touch_device());

ОНОВЛЕННЯ 1

document.createEvent("TouchEvent")почали повертатися trueв останньому хромі (ст. 17). Modernizr це нещодавно оновив. Перевірте тест Modernizr тут .

Оновіть свою функцію так, щоб вона працювала:

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

console.log(is_touch_device1());

ОНОВЛЕННЯ 2

Я виявив, що вищезгадане не працює на IE10 (повертає помилку на MS Surface). Ось виправлення:

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

ОНОВЛЕННЯ 3

'onmsgesturechange' in windowповернеться істинним у деяких версіях IE для настільних комп'ютерів, так що це не є надійним. Це працює трохи надійніше:

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

ОНОВЛЕННЯ 2018 року

Час минає, і є нові, кращі способи перевірити це. Я в основному витягнув і спростив спосіб перевірки Модернізра:

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

Тут вони використовують нестандартну touch-enabledмедіа-запит, що, на мою думку, є дивним і поганим звичаєм. Але ей, в реальному світі я думаю, що це працює. Надалі (коли їх підтримуватимуть усі), ці функції медіа-запитів можуть дати ті самі результати: pointerі hover.

Перевірте джерело того, як це робить Modernizr .

Хорошу статтю, яка пояснює проблеми з виявленням дотику, див: Стю Кокс: Не вдається виявити сенсорний екран .


20
Подвійний вибух передає значення булевому значенню, змушуючи функцію повертати trueабо false. Більше про це можна прочитати тут: stackoverflow.com/questions/4686583/…
Роб Флахерті

2
Це не працює з Opera Mobile 10 або Internet Explorer Mobile 6 (Windows Mobile 6.5).
подвійнийJ20

17
Подвійний NOT (!!) є зайвим, оскільки inоператор вже оцінює булеву форму.
Стів

11
'onmsgesturechange'оцінює істину навіть на пристроях без дотику (ПК). window.navigator.msMaxTouchPointsздається, точніше. Знайшов його тут .
Стів

6
Це відповідає дійсності для IE10 в Windows 8, навіть якщо на моєму екрані немає сенсорних датчиків. Я оновив свій старий ноутбук з Windows 7 до Windows 8.
Pwner

120

Оскільки Modernizr не виявляє IE10 в Windows Phone 8 / WinRT, простим рішенням для веб-переглядачів є:

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

Вам потрібно колись перевірити, як пристрій несподівано не підтримує чи не підтримує дотик, тому просто зберігайте його в змінній, щоб ви могли використовувати її в кілька разів ефективніше.


3
"onmsgesturechange" у вікні також виявляє "настільний" IE10 на нетипових пристроях, тому це не є надійним методом визначення дотику.
Метт Стоу

6
Ця відповідь повинна була бути прийнята, оскільки вона найкраща та найпростіша та найсучасніша. У функції я вважаю, що це було б більш послідовно: return !!('ontouchstart' in window) || !!('msmaxtouchpoints' in window.navigator);(поєднуючи обидві відповіді) Добре працює і в IE10!
Йєті

Це має бути прийнятою відповіддю. 'onmsgesturechange' in windowповертає справжнє на робочому столі IE10 навіть тоді, коли можливий дотик
Сем Торнтон

6
Все, що вам потрібно:function isTouchDevice() { return 'ontouchstart' in window || !!(navigator.msMaxTouchPoints);}
GFoley83

1
Навіть пропозиція GFoleys "ontouchstart" у вікні || !! (navigator.msMaxTouchPoints); повертає фальшиві позитивні версії в Chrome 30 листопада 2014 р.
Том Андерсен,

37

Використовуючи всі коментарі вище, я зібрав наступний код, який працює для моїх потреб:

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

Я перевірив це на iPad, Android (браузер і Chrome), програмі Blackberry Playbook, iPhone 4s, Windows Phone 8, IE 10, IE 8, IE 10 (Windows 8 з сенсорним екраном), Opera, Chrome і Firefox.

Наразі він не працює в Windows Phone 7, і я поки не зміг знайти рішення для цього браузера.

Сподіваюся, хтось вважає це корисним.


Чи є причина, яку ви не можете використовувати: функція is_touch_device () {return !! ('ontouchstart' у вікні) || !! ('msmaxtouchpoints' у навігаторі); };
sidonaldson

використання функції буде працювати, але я, як правило, люблю використовувати метод змінної вище, тому він тестується лише один раз і швидше, коли я перевіряю пізніше свій код. Також я виявив, що мені потрібно перевірити, чи не було msMaxTouchPoints більше 0, оскільки IE 10 в Windows 8 без сенсорного екрана повертав 0 як msMaxTouchPoints.
Девід

повертається trueна мій Firefox 32 на Windows 7 :(
vsync

Firefox 33 і 33.1 в Windows 8 показують помилковість правильно в моїй системі. Якщо ви оновите Firefox до останньої версії, він все ще повернеться правдою? У вас, можливо, на вашій машині встановлено пристрій, який може змусити Firefox помилково думати, що ваша машина має дотик?
Девід

>>> "ontouchstart" у вікні >>> true FF 51.0.1 на ubuntu
Ravi Gadhia

25

З моменту впровадження функцій медіа для взаємодії ви просто можете:

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

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

Оновлення (завдяки коментарям): Наведене вище рішення полягає у виявленні, чи є "грубим покажчиком" - зазвичай сенсорним екраном - основним пристроєм введення. Якщо ви хочете визначити, якщо пристрій, наприклад, миша, також має сенсорний екран, ви можете any-pointer: coarseзамість цього використовувати .

Для отримання додаткової інформації дивіться тут: Визначте, що у веб-переглядачі немає миші та є лише сенсорним


3
Це, безумовно, найкраще рішення, дякую! Хоча я б рекомендував використовувати, (pointer: coarse)оскільки ви, швидше за все, орієнтуєтесь лише на первинний вклад. Можна використовувати у виробництві, оскільки декілька непідтримуваних браузерів є лише настільними. Про це є чудова стаття про css-трюки .
Фабіан фон Еллертс

2
Це єдине тестоване рішення, яке працює у будь-якій ситуації. Дякую!
kaiserkiwi

20

Мені подобається цей:

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

alert(isTouchDevice());

12
Немає необхідності використовувати потрійний вираз, щоб повернути булеве значення. Просто використовуйте вираз, щоб повернути булеве значення. function isTouchDevice(){ return (window.ontouchstart !== undefined); }
Тім Вермален

1
Ви також можете просто скористатися: var isTouch = 'ontouchstart' in window;проте це не працює з найновішим Chrome (v31), var isTouch = 'createTouch' in window.document;він все ще працює.
Олів'є

2
Як уже говорилося в коментарях до раніше прийнятого питання. "Modernizr не тестує на сенсорні екрани. Він перевіряє наявність сенсорних подій у браузері". Ваша функція технічно маєTouchEvents () не isTouchDevice ()
hexalys

Зверніть увагу, що лише тестування подібних методів touchstartне зможе розпізнати Surface як сенсорний пристрій, оскільки IE використовує pointerподії.
CookieMonster

1
Можливо, @Nis був правий, але в Firefox 39 він правильно повертає помилку.
Дан Даскалеску

17

Якщо ви використовуєте Modernizr , це дуже просто у використанні, Modernizr.touchяк згадувалося раніше.

Однак я вважаю за краще використовувати комбінацію Modernizr.touchта тестування агента користувача, аби бути безпечною.

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, ви можете просто замінити Modernizr.touchфункцію вище('ontouchstart' in document.documentElement)

Також зауважте, що тестування агента користувача iemobileдасть вам ширший спектр виявлених мобільних пристроїв Microsoft, ніж Windows Phone.

Дивіться також це питання


8
Багато бонусних балів за "зробити щось зворушливо" та "не можу доторкнутися до цього"
Лі Саксон

ви перевіряєте кілька разів на одних і тих же пристроях і робите кілька Regexes, коли ви могли використовувати лише один. плюс, ви робите нечутливі до регістру регекси, але рядок уже нижній регістр.
цезарсол

1
цього має бути достатньо:/(iphone|ipod|ipad|android|iemobile|blackberry|bada)/.test(window.navigator.userAgent.toLowerCase())
цезарсол

Будь-яка причина зменшити малі чи зробити невідповідними регістри? Коли "iOS", "Android" або "IEMobile" використовують інші корпуси?
Генрік N

14

Ми спробували реалізацію модернізатора, але виявлення сенсорних подій більше не відповідає (IE 10 має сенсорні події на робочому столі Windows, IE 11 працює, оскільки випали сенсорні події та додано api вказівника).

Тому ми вирішили оптимізувати веб-сайт як сенсорний сайт, доки ми не знаємо, який тип вводу має користувач. Це надійніше, ніж будь-яке інше рішення.

Наші дослідження стверджують, що більшість користувачів настільних ПК пересуваються мишкою по екрану, перш ніж натиснути, тож ми можемо виявити їх і змінити поведінку, перш ніж вони зможуть натиснути або навести на нього що-небудь.

Це спрощена версія нашого коду:

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

на комп’ютерах сьогодні є як сенсорний, так і мишачий ... ви повинні розрізняти. це абсолютно необхідно знати, чи це лише дотик, миша чи те й інше. 3 різних стани.
vsync

1
Так, ти маєш рацію, але це дуже важко. У кращому випадку ваша програма призначена для використання будь-яким вхідним контролером і не важливо, чи є у користувача сенсорний екран, миша, клавіатура або всі разом.
Мартін Ланч

1
Поведінка користувача коштує більше, ніж реальна інформація про те, яким пристроєм користувач користується. Коли ви знаєте, що у користувача є миша, сенсорний екран і клавіатура - що тоді? Поводьтеся з поведінкою (миші, натискання, натискання клавіш тощо). Користувачі можуть змінити тип введення під час "виконання", це справжня проблема, коли ви розробляєте реальну програму, яка використовується з 8 по 5 без перезавантаження.
Martin Lantzsch

2
+1 Прагматично це найкраща відповідь для мене. Наприклад, у мене є сітки даних. Ці сітки даних покажуть "піктограму редагування" для торкання для редагування або контекстне меню для додаткових опцій. Якщо рух миші виявлено, я знімаю піктограму (економить місце в сітці) і користувачі можуть двічі клацнути або клацнути правою кнопкою миші.
prograhammer

3
хром на сенсорних пристроях час від часу запускає миші
pstanton

9

Робоча скрипка

Я домігся цього;

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

@DanBeaulieu, будь ласка, будьте конкретні для пристрою, тому що у мене є телефон Windows, для якого він працює добре, також я використовував його у своїй програмі, яка є QA: ED, я ще раз перевірте це і оновив відповідь. Вибачте за незручності
Аамір Шахзад

Не впевнений, який рік, це професійна поверхня Windows, яка належить співпрацівнику. Після додавання модернізатора ми працювали.
Ден Болье

Це правильно повідомило про нетиповий сенсор на моїй машині Windows 7 та торкніться ноутбука Windows 8 з сенсорним екраном та телефону Android 4.4 MotoX.
Клей Ніколс

Дає хибну позитиву в Chrome (46) на моєму Mac
Патрік Фабризіус

9

Є щось краще, ніж перевірити, чи є у них сенсорний екран, це перевірити, чи вони ним користуються, плюс це легше перевірити.

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

6

Цей працює добре навіть у планшетах 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

Я використовував фрагменти коду вище, щоб визначити, чи є дотик, тому мій iframe fancybox відображатиметься на настільних комп’ютерах, а не на дотик. Я помітив, що Opera Mini для Android 4.0 все ще реєструється як безконтактний пристрій при використанні коду blmstr. (Хтось знає, чому?)

Я закінчив використовувати:

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

Ви можете, будь ласка, пояснити, чому ви не використовуєте один дзвінок у відповідність з одним регулярним виразом /iPhone|iPod|iPad|Android|BlackBerry/?
користувач907860

Opera Mini здійснює рендерінг на серверах Opera, а не на самому пристрої, тому це так дивно.
блюзмоун

4

Найбільша «готча» із спробою виявити дотик - це на гібридних пристроях, які підтримують як дотик, так і трекпад / мишу. Навіть якщо ви зможете правильно визначити, чи підтримує пристрій користувача дотик, вам потрібно дійсно виявити, яким пристроєм введення користувач користується в даний час . Тут детально написано цей виклик та можливе рішення .

По суті, підхід до з'ясування того, чи користувач просто торкнувся екрана чи використовував мишу / трекпад замість цього, це зареєструвати як touchstartі mouseoverподії на сторінці:

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

Дотикова дія спричинить обидві ці події, хоча попереднє ( touchstart) завжди перше на більшості пристроїв. Отже, розраховуючи на цю передбачувану послідовність подій, ви можете створити механізм, який динамічно додає або видаляє can-touchклас до кореня документа, щоб відобразити поточний тип введення користувача на даний момент у документі:

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

Детальніше тут .


3

Перегляньте цю публікацію , вона дає дійсно приємний фрагмент коду, що робити при виявленні сенсорних пристроїв або що робити, якщо викликається подія 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

Я б не використовував ширину екрана, щоб визначити, чи пристрій є сенсорним пристроєм. Є сенсорні екрани набагато більше 699 пікселів, подумайте про Windows 8. Navigatior.userAgent може бути приємно переосмислити помилкові пости.

Я рекомендую переглянути цю проблему на Modernizr.

Ви хочете перевірити, чи пристрій підтримує сенсорні події чи сенсорний пристрій. На жаль, це не те саме.


3

Ні, це неможливо. Відмінні відповіді надаються лише частково, тому що будь-який метод дасть помилкові позитиви та хибні негативи. Навіть веб-переглядач не завжди знає, чи є сенсорний екран через API OS, і факт може змінюватися під час сеансу роботи в браузері, особливо за домовленостями типу KVM.

Детальнішу інформацію див. У цій чудовій статті:

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

У статті пропонується переглянути свої припущення, які змушують виявити сенсорні екрани, вони, ймовірно, помиляються. (Я перевірив власне на свою програму, і мої припущення справді були невірними!)

Стаття завершує:

Примітка, припустимо, у кожного є сенсорний екран. Користувачі миші можуть користуватися великими елементами управління інтерфейсом набагато легше, ніж сенсорні користувачі можуть використовувати маленькі. Те саме стосується і держав, що наближаються.

Припустимо, що для подій та взаємодій будь-хто може мати сенсорний екран. Здійснюйте взаємодію між клавіатурою, мишею та сенсорним керуванням, не забезпечуючи жодного блокування.


3

Багато з них працюють, але або вимагають jQuery, або вкладиші JavaScript скаржаться на синтаксис. Зважаючи на ваше початкове запитання, ви задаєте "JavaScript" (не jQuery, не Modernizr) спосіб вирішення цього питання, ось проста функція, яка працює кожного разу. Це також приблизно як мінімум, як ви можете отримати.

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

console.log(isTouchDevice());

Останньою перевагою, яку я зазначу, є те, що цей код є фреймворком та пристроєм. Насолоджуйтесь!


function isTouchScreen() { return window.matchMedia('(hover: none)').matches;}Це працювало для мене, тому я тут додаю внесок у цю відповідь, оскільки я також очікував, що ванільна JS нитка, коли Google привів мене сюди.
Даніель Лаведоніо де Ліма

2

Схоже, Chrome 24 тепер підтримує сенсорні події, ймовірно, для Windows 8. Отже, розміщений тут код більше не працює. Замість того, щоб намагатися визначити, чи підтримує браузер сенсорний зв’язок, я тепер прив’язую події як дотику, так і клацання, і переконуюсь, що викликається лише одна:

myCustomBind = function(controlName, callback) {

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

    callback.call();
  });
};

А потім називаючи це:

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

Сподіваюся, це допомагає!


1
Пов’язана тема, stackoverflow.com/questions/12566306/…
Ефір

2

Весь підтримуваний браузер, окрім Firefox для робочого столу, завжди ПРАВИЛЬНИЙ, оскільки Firefox для робочого столу підтримує адаптивний дизайн для розробника, навіть якщо ви натискаєте Touch-Button чи ні!

Сподіваюся, Mozilla це виправить у наступній версії.

Я використовую Firefox 28 настільний.

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

це все ще версія 32.0, і вони її ще не виправили! божевільний. чому це неможливо змінити ?? Це завжди повертається true:(
vsync

2

jQuery v1.11.3

У наданих відповідях є багато хорошої інформації. Але останнім часом я витратив багато часу, намагаючись фактично зв'язати все разом у робочому рішенні для досягнення двох речей:

  1. Визначте, що використовуваний пристрій - це пристрій типу сенсорного екрана.
  2. Визначте, що пристрій прослухано.

Окрім цієї публікації та виявлення пристроїв із сенсорним екраном за допомогою Javascript , я вважав це повідомлення Патріком Лауке надзвичайно корисним: https://hacks.mozilla.org/2013/04/detecting-touch-its-the-why-not-the-how /

Ось код ...

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

Важливо! The*.on( events [, selector ] [, data ], handler ) потреби спосіб мати селектор, як правило , елемент, який може обробляти «touchstart» подія, або будь-яке інше подібне подія , пов'язане зі штрихами. У цьому випадку це гіперпосилання елемент "а".

Тепер вам не потрібно обробляти звичайне клацання миші в JavaScript, тому що ви можете використовувати CSS для обробки цих подій, використовуючи селектори для елемента гіперпосилання "а", наприклад:

/* unvisited link */
a:link 
{

}

/* visited link */
a:visited 
{

}

/* mouse over link */
a:hover 
{

}

/* selected link */
a:active 
{

}

Примітка. Є й інші селектори ...


1
var isTouchScreen = 'createTouch' in document;

або

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

була б більш ретельна перевірка.


3
Було б добре зазначити, що uaстосується navigator.userAgent. Також виявлення за шириною екрана може дати помилковий результат, якщо хтось відкриє браузер у не повноекранному режимі.
HoLyVieR


1

Я також багато боровся з різними варіантами того, як визначити в Javascript, відображається сторінка на пристрої з сенсорним екраном чи ні. IMO, на даний момент, не існує реальної можливості для належного виявлення цього варіанту. Браузери або повідомляють про події дотику на настільних машинах (оскільки ОС, можливо, готові дотику), або деякі рішення працюють не на всіх мобільних пристроях.

Врешті-решт я зрозумів, що дотримуюся неправильного підходу з самого початку: Якщо моя сторінка повинна виглядати схоже на пристроях, що торкаються та не торкаються, мені, можливо, не слід було б турбуватися про виявлення властивості: Мій сценарій був відключити підказки через кнопки на сенсорних пристроях, оскільки вони призводять до подвійних натискань, де я хотів одним натисканням активувати кнопку.

Моє рішення полягало в тому, щоб переробити перегляд, щоб жодна підказка не була потрібна для кнопки, і врешті-решт мені не потрібно було виявляти сенсорний пристрій від Javascript методами, які мають всі свої недоліки .


1

Ви можете встановити модернізатор і використовувати простий сенсорний захід. Це дуже ефективно і працює на кожному пристрої, який я перевірив, включаючи поверхню вікон!

Я створив 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
Ласкаво просимо до SO! Код сам по собі (як і коментований код) рідко є відповіддю. Ви можете покращити цю відповідь, додавши пояснення фрагменту.
ebarr

1

Здається, практична відповідь, яка враховує контекст:

1) Загальнодоступний сайт (без входу в систему)
Зашифруйте інтерфейс користувача, щоб працювати з обома параметрами разом.

2) Увійти на сайт
Укажіть, чи відбувся переміщення миші у формі входу, і збережіть це у прихованому вході. Значення передається за допомогою облікових даних для входу та додається до сеансу користувача , тому воно може бути використане протягом тривалості сеансу.

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

(+1 до @Dave Burt та +1 до @Martin Lantzsch щодо їх відповідей)


1

Проблема

Завдяки гібридним пристроям, які використовують комбінацію сенсорного та мишачого введення, вам потрібно мати можливість динамічно змінювати стан / змінну, яка контролює, чи повинен працювати фрагмент коду, якщо користувач є користувачем, який працює на дотику чи ні.

Сенсорні пристрої також спрацьовують mousemoveпід час крана.

Рішення

  1. Припустимо, що натискання невірно при навантаженні.
  2. Зачекайте, поки touchstartподія буде запущена, а потім встановіть її на істину.
  3. Якщо сенсорний запуск був запущений, додайте обробник миші.
  4. Якщо час між стрільбою подій двох рухів миші становило менше 20 мс, припустимо, вони використовують мишу в якості введення. Видаліть подію, оскільки вона більше не потрібна, а рух миші - дорога подія для пристроїв миші.
  5. Як тільки сенсорний запуск знову запускається (користувач повернувся до використання touch), змінна повертається до значення true. І повторіть процес, щоб він визначався динамічно. Якщо якимось диво-рухом миші двічі звільняються від дотику на дотик (в моєму тестуванні це практично неможливо зробити протягом 20 мс), наступний сенсорний запуск поверне його до істинного.

Тестовано на Safari iOS та Chrome для Android.

Примітка: не на 100% впевненість у покажчиках подій для MS Surface тощо.

Codepen demo


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

Власне, я досліджував це питання і розглядаю всі ситуації. тому що це велике питання і в моєму проекті. Тож я дійшов до нижченаведеної функції, вона працює для всіх версій усіх браузерів на всіх пристроях:

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

Підказка : Безумовно,isTouchDeviceсправедливий повертаєbooleanзначення.


0

supportОб'єкт jQuery :

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

А тепер ви можете перевірити це де завгодно, як це:

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

0

Це, здається, для мене зараз добре працює:

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

Коли миша приєднана, з досить високою швидкістю (я б сказав практично 100%) можна вважати, що користувач переміщає мишу хоча б на невелику відстань після того, як сторінка готова - без жодного клацання. Нижче наведений механізм виявляє це. Якщо це виявлено, я вважаю це ознакою відсутньої підтримки дотику або, якщо вона підтримується, має незначне значення, коли миша використовується. Сенсорний пристрій передбачається, якщо його не виявлено.

EDIT Цей підхід може відповідати не всім цілям. З його допомогою можна керувати функціоналом, який активується на основі взаємодії з користувачем на завантаженій сторінці, наприклад, для перегляду зображень. Код, що наведено нижче, також залишить подія миші прив'язаною до пристроїв без миші, як це виділяється зараз. Інші підходи можуть бути кращими.

Приблизно, це виглядає так (вибачте за jQuery, але подібне в чистому 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;
}));
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.