Как я могу обнаружить поддержку сенсорного экрана в JavaScript?

В прошлом при обнаружении того, поддерживает ли устройство сенсорные события в JavaScript, мы могли бы сделать что-то вроде этого:

var touch_capable = ('ontouchstart' in document.documentElement);

Однако Google Chrome (17.x.x +) возвращает true для вышеуказанной проверки, даже если базовое устройство не поддерживает события касания. Например, запуск вышеуказанного кода в Windows 7 возвращает true, и поэтому, если мы объединим его с чем-то вроде:

var start_evt = (touch_capable) ? 'ontouchstart' : 'onmousedown';

В Google Chrome событие никогда не запускается, так как мы привязываемся к ontouchstart. Короче говоря, знает ли кто-нибудь надежный способ обойти это? В настоящее время я выполняю следующую проверку:

var touch_capable = ('ontouchstart' in document.documentElement && navigator.userAgent.toLowerCase().indexOf('chrome') == -1)

Что далеко от идеала...

Ответ 1

Правильный ответ - обрабатывать оба типа событий - они не являются взаимоисключающими.

Для более надежного тестирования сенсорной поддержки также найдите window.DocumentTouch && document instanceof DocumentTouch, который является одним из тестов, используемых Modernizr

Еще лучше, просто используйте Modernizr самостоятельно, и пусть это сделает обнаружение функции для вас.

Обратите внимание, что вы не можете предотвратить ложные срабатывания, поэтому моя первая строка выше - вы должны поддерживать оба.

Ответ 2

Это модификация того, как Modernizr выполняет сенсорное обнаружение, с дополнительной поддержкой работы с сенсорными устройствами IE10 +.

var isTouchCapable = 'ontouchstart' in window ||
 window.DocumentTouch && document instanceof window.DocumentTouch ||
 navigator.maxTouchPoints > 0 ||
 window.navigator.msMaxTouchPoints > 0;

Он не является надежным, поскольку обнаружение сенсорного устройства, по-видимому, невозможно.

Ваш пробег может варьироваться:

  • Старые сенсорные устройства только эмулируют события мыши.
  • Некоторые браузеры и настройки ОС могут включать сенсорные API, если сенсорный экран не подключен.
  • В гибридной среде mouse/touch/trackpad/pen/keyboard это не указывает, какой вход используется, только в том, что браузер трогателен - он обнаруживает, может ли браузер принимать или эмулировать сенсорный ввод. Например, пользователь может в любой момент переключиться с использования мыши на касание экрана на сенсорном ноутбуке или планшете, подключенном к мыши.

Update: Совет. Не используйте обнаружение сенсорных возможностей для управления и указания поведения пользовательского интерфейса, вместо этого использовать прослушиватели событий. Дизайн для события click/touch/keyup, а не устройства, обнаружение сенсорной способности обычно используется для сохранения затрат процессора/памяти на добавление прослушивателя событий. Один из примеров того, где обнаружение касания может быть полезным и целесообразным:

if (isTouchCapable) {
    document.addEventListener('touchstart', myTouchFunction, false); 
}

Ответ 3

Вам следует рассмотреть возможность использования хорошо протестированного (и кросс-браузерного) тестирования TouchPress.

Со своего сайта:

// bind to mouse events in any case

if (Modernizr.touch){
   // bind to touchstart, touchmove, etc and watch `event.streamId`
} 

http://modernizr.github.com/Modernizr/touch.html

Ответ 4

Ну, старый вопрос, но, чтобы сделать это без библиотеки, я создал следующее решение - просто позвольте событиям говорить для себя - когда вы видите события touch, просто отключите обработку mouse события.

В coffescript будет выглядеть так:

           hasTouch = false
           mouseIsDown = false
           @divs.on "touchstart", (e)->
              hasTouch = true
              touchstart(e.timeStamp,e.originalEvent.touches[0].pageX);
              return true
           @divs.on "mousedown", (e)->
              mouseIsDown = true;
              touchstart(e.timeStamp,e.clientX) if not hasTouch
              return true

           @divs.on 'touchmove', (e) ->
              touchmove(e.timeStamp,e.originalEvent.touches[0].pageX);
              return true;
           @divs.on 'mousemove', (e) ->
              touchmove(e.timeStamp,e.clientX) if mouseIsDown and not hasTouch 
              return true;

           @divs.on 'touchend', (e) ->
              touchend();
              return true
           @divs.on 'mouseup', (e) ->
              mouseIsDown = false;
              touchend() if not hasTouch
              return true

Просто определите функции для touchstart, move и end, содержащие фактическую логику....