我编写了一个jQuery插件,可以在桌面和移动设备上使用。我想知道是否有一种方法可以用JavaScript来检测设备是否具有触摸屏功能。我使用jquery-mobile.js来检测触摸屏事件,它适用于iOS, Android等,但我也想根据用户的设备是否有触摸屏来编写条件语句。

这可能吗?


当前回答

试图检测触控的最大“陷阱”是同时支持触控和触控板/鼠标的混合设备。即使你能够正确地检测用户的设备是否支持触摸,你真正需要做的是检测用户当前使用的输入设备。这里有一份关于这个挑战的详细报告和可能的解决方案。

基本上,判断用户是触摸屏幕还是使用鼠标/触控板的方法是在页面上注册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
})();

详情请点击这里。

其他回答

我使用上面的代码片段来检测是否有触摸,所以我的iframe会在台式电脑上显示,而不是在触摸时显示。我注意到Android 4.0的Opera Mini在单独使用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>

使用上面所有的注释,我已经组装了下面的代码,是为我的需要工作:

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

我在iPad、Android(浏览器和Chrome)、黑莓Playbook、iPhone 4s、Windows Phone 8、IE 10、IE 8、IE 10(带触摸屏的Windows 8)、Opera、Chrome和Firefox上进行了测试。

它目前在Windows Phone 7上无法运行,我还没有找到针对该浏览器的解决方案。

希望有人觉得这有用。

许多这些工作,但要么需要jQuery,或javascript linters抱怨语法。考虑到你最初的问题要求“JavaScript”(不是jQuery,不是Modernizr)来解决这个问题,这里有一个简单的函数,每次都能工作。这也是你能得到的最小值。

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

console.log(isTouchDevice());

我要提到的最后一个好处是,该代码是框架和设备不可知的。享受吧!

jQuery v1.11.3

答案中有很多有用的信息。但是,最近我花了很多时间试图将所有事情结合到一个有效的解决方案中,以完成两件事:

检测正在使用的设备是触摸屏类型的设备。 检测设备被窃听。

除了这篇文章和用Javascript检测触摸屏设备,我发现Patrick Lauke的这篇文章非常有用: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;
    }
});

重要!*。On (events [, selector] [, data], handler)方法需要有一个选择器,通常是一个元素,它可以处理“touchstart”事件,或任何其他与触摸相关的类似事件。在本例中,它是超链接元素“a”。

现在,你不需要在JavaScript中处理常规的鼠标点击,因为你可以使用CSS来处理这些事件,使用超链接“a”元素的选择器,如下所示:

/* unvisited link */
a:link 
{

}

/* visited link */
a:visited 
{

}

/* mouse over link */
a:hover 
{

}

/* selected link */
a:active 
{

}

注意:还有其他的选择器…

事实上,我研究了这个问题并考虑了各种情况。因为这在我的项目中也是一个大问题。所以我达到了下面的功能,它适用于所有设备上所有浏览器的所有版本:

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只返回布尔值。