我编写了一个jQuery插件,可以在桌面和移动设备上使用。我想知道是否有一种方法可以用JavaScript来检测设备是否具有触摸屏功能。我使用jquery-mobile.js来检测触摸屏事件,它适用于iOS, Android等,但我也想根据用户的设备是否有触摸屏来编写条件语句。
这可能吗?
我编写了一个jQuery插件,可以在桌面和移动设备上使用。我想知道是否有一种方法可以用JavaScript来检测设备是否具有触摸屏功能。我使用jquery-mobile.js来检测触摸屏事件,它适用于iOS, Android等,但我也想根据用户的设备是否有触摸屏来编写条件语句。
这可能吗?
当前回答
我们尝试了modernizr实现,但检测触摸事件不再一致(IE 10有触摸事件在windows桌面,IE 11工作,因为已经放弃触摸事件和添加指针api)。
所以我们决定优化网站作为一个触摸网站,只要我们不知道用户有什么输入类型。这比任何其他解决方案都更可靠。
我们的研究表明,大多数桌面用户在点击之前会将鼠标移到屏幕上,所以我们可以检测到他们,并在他们能够点击或悬停任何东西之前改变他们的行为。
这是我们代码的简化版本:
var isTouch = true;
window.addEventListener('mousemove', function mouseMoveDetector() {
isTouch = false;
window.removeEventListener('mousemove', mouseMoveDetector);
});
其他回答
许多这些工作,但要么需要jQuery,或javascript linters抱怨语法。考虑到你最初的问题要求“JavaScript”(不是jQuery,不是Modernizr)来解决这个问题,这里有一个简单的函数,每次都能工作。这也是你能得到的最小值。
function isTouchDevice() {
return !!window.ontouchstart;
}
console.log(isTouchDevice());
我要提到的最后一个好处是,该代码是框架和设备不可知的。享受吧!
关于如何在Javascript中检测页面是否显示在触摸屏设备上,我也遇到了很多困难。 在我看来,到目前为止,还没有真正的选项可以正确地检测这个选项。 浏览器要么报告桌面机器上的触摸事件(因为操作系统可能已经准备好触摸了),要么某些解决方案不能在所有移动设备上工作。
最后,我意识到我从一开始就采取了错误的方法: 如果我的页面在触摸和非触摸设备上看起来相似,我可能根本不需要担心检测属性: 我的方案是禁用触摸设备上的按钮上的工具提示,因为它们会导致双击,而我希望通过一次点击来激活按钮。
我的解决方案是重构视图,这样按钮上就不需要工具提示了,最后我也不需要用Javascript的方法来检测触摸设备了,因为这些方法都有自己的缺点。
这个问题
由于混合设备使用触摸和鼠标输入的组合,你需要能够动态地改变状态/变量,控制一段代码是否应该运行,如果用户是触摸用户或不是。
触控设备也可以在点击时触发鼠标移动。
解决方案
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);
}
如果您使用Modernizr,使用Modernizr是非常容易的。如前所述,触摸。
但是,我更喜欢使用Modernizr的组合。触摸和用户代理测试,只是为了安全。
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。在document.documentElement中使用('ontouchstart')
还要注意,测试用户代理iemobile将为您提供比Windows Phone更广泛的检测到的微软移动设备。
也可以看到这个SO问题
我使用:
if(jQuery.support.touch){
alert('Touch enabled');
}
jQuery mobile 1.0.1