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

这可能吗?


当前回答

不,不可能。给出的优秀答案永远都是片面的,因为任何给定的方法都会产生假阳性和假阴性。由于操作系统api的原因,甚至浏览器也不总是知道是否存在触摸屏,而且在浏览器会话期间,这一事实可能会发生变化,特别是使用kvm类型的安排。

详见这篇优秀的文章:

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

这篇文章建议你重新考虑那些让你想要检测触摸屏的假设,它们可能是错误的。(我检查了我自己的应用程序,我的假设确实是错误的!)

文章总结道:

对于布局,假设每个人都有触摸屏。鼠标用户可以使用 大型UI控件比触摸用户使用小控件容易得多 的人。悬浮状态也是如此。 对于事件和交互,假设任何人都有触摸屏。 实现键盘、鼠标和触摸交互, 确保互不妨碍。

其他回答

我喜欢这个:

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

alert(isTouchDevice());

我使用上面的代码片段来检测是否有触摸,所以我的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>

我会避免使用屏幕宽度来判断一个设备是否是触控设备。触摸屏比699px大得多,想想Windows 8。Navigatior。userAgent可以很好地覆盖误报。

我建议你在Modernizr上看看这一期。

你是想测试设备是否支持触摸事件,还是一个触摸设备。不幸的是,这不是一回事。

这个问题

由于混合设备使用触摸和鼠标输入的组合,你需要能够动态地改变状态/变量,控制一段代码是否应该运行,如果用户是触摸用户或不是。

触控设备也可以在点击时触发鼠标移动。

解决方案

Assume touch is false on load. Wait until a touchstart event is fired, then set it to true. If touchstart was fired, add a mousemove handler. If the time between two mousemove events firing was less than 20ms, assume they are using a mouse as input. Remove the event as it's no longer needed and mousemove is an expensive event for mouse devices. As soon as touchstart is fired again (user went back to using touch), the variable is set back to true. And repeat the process so it's determined in a dynamic fashion. If by some miracle mousemove gets fired twice on touch absurdly quickly (in my testing it's virtually impossible to do it within 20ms), the next touchstart will set it back to true.

在Safari iOS和Chrome for Android上进行了测试。

注意:不是100%确定的指针事件为MS Surface等。

Codepen演示


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

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 
{

}

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