Как лучше всего обнаружить устройство с «сенсорным экраном» с помощью JavaScript? - PullRequest
375 голосов
/ 27 января 2011

Я написал плагин jQuery для использования на настольных и мобильных устройствах. Я задавался вопросом, есть ли способ с JavaScript, чтобы обнаружить, если устройство имеет возможность сенсорного экрана. Я использую jquery-mobile.js для обнаружения событий сенсорного экрана, и он работает на iOS, Android и т. Д., Но я также хотел бы написать условные операторы, основанные на том, имеет ли устройство пользователя сенсорный экран.

Это возможно?

Ответы [ 36 ]

6 голосов
/ 10 октября 2013

Этот работает хорошо даже в планшетах 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 голосов
/ 13 января 2012

Я использовал фрагменты кода выше, чтобы определить, нужно ли нажимать, чтобы мои встроенные рамки 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>
4 голосов
/ 23 октября 2016

Самая большая проблема с попыткой обнаружить касание - на гибридных устройствах, которые поддерживают как сенсорное управление, так и трекпад / мышь.Даже если вы в состоянии правильно определить, поддерживает ли устройство пользователя касание, вам действительно нужно определить, какое устройство ввода пользователь использует .Подробное описание этой проблемы и возможное решение здесь .

В основном подход к выяснению, касался ли пользователь экрана или вместо этого использовал мышь / трекпад, заключается в регистрации на странице событий 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 голосов
/ 16 декабря 2014

Нет, это невозможно. Превосходные ответы даны только частично, потому что любой данный метод будет давать ложные срабатывания и ложные отрицания. Даже браузер не всегда знает, присутствует ли сенсорный экран из-за API-интерфейсов операционной системы, и этот факт может измениться во время сеанса браузера, особенно с соглашениями типа KVM.

Подробности в этой прекрасной статье:

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

Статья предлагает вам пересмотреть предположения, которые заставляют вас хотеть обнаруживать сенсорные экраны, они, вероятно, ошибочны. (Я проверил свое собственное приложение, и мои предположения были неверны!)

В статье делается вывод:

Предполагается, что для макетов у всех есть сенсорный экран. Пользователи мыши могут использовать большие элементы управления пользовательским интерфейсом гораздо проще, чем сенсорные пользователи могут использовать маленькие из них. То же самое касается состояний при наведении.

Для событий и взаимодействий предположим, что у любого может быть сенсорный экран. Реализовать взаимодействие клавиатуры, мыши и касания друг с другом, чтобы никто не блокировал друг друга.

3 голосов
/ 16 декабря 2012

Я бы не использовал ширину экрана, чтобы определить, является ли устройство сенсорным. Существуют сенсорные экраны, намного большие, чем 699 пикселей, подумайте о Windows 8. Navigatior.userAgent может быть хорошим, чтобы переопределить ложные предположения.

Я бы порекомендовал проверить эту проблему на Modernizr.

Вы хотите проверить, поддерживает ли устройство сенсорные события или является сенсорным устройством. К сожалению, это не одно и то же.

3 голосов
/ 23 декабря 2011

Ознакомьтесь с этой публикацией , в ней приведен действительно хороший фрагмент кода, описывающий, что делать при обнаружении сенсорных устройств или что делать, если вызывается событие сенсорного запуска:

$(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();
}
2 голосов
/ 08 октября 2014

Многие из них работают, но требуют либо jQuery, либо линтеры javascript жалуются на синтаксис.Учитывая, что ваш первоначальный вопрос требует "JavaScript" (не jQuery, не Modernizr) способа решения этой проблемы, вот простая функция, которая работает каждый раз.Он также настолько минимален, насколько вы можете получить.

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

console.log(isTouchDevice());

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

2 голосов
/ 01 февраля 2013

Похоже, что Chrome 24 теперь поддерживает сенсорные события, вероятно, для Windows 8. Поэтому код, размещенный здесь, больше не работает.Вместо того, чтобы пытаться определить, поддерживается ли касание браузером, я теперь связываю события касания и нажатия и проверяю, вызывается ли только одно:

myCustomBind = function(controlName, callback) {

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

    callback.call();
  });
};

И затем вызываю его:

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

Надеюсь, это поможет!

1 голос
/ 19 марта 2012

Я использую:

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

в jQuery mobile 1.0.1

1 голос
/ 03 ноября 2011
var isTouchScreen = 'createTouch' in document;

или

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

будет более тщательной проверкой, я полагаю.

...