我编写了一个jQuery插件,可以在桌面和移动设备上使用。我想知道是否有一种方法可以用JavaScript来检测设备是否具有触摸屏功能。我使用jquery-mobile.js来检测触摸屏事件,它适用于iOS, Android等,但我也想根据用户的设备是否有触摸屏来编写条件语句。
这可能吗?
我编写了一个jQuery插件,可以在桌面和移动设备上使用。我想知道是否有一种方法可以用JavaScript来检测设备是否具有触摸屏功能。我使用jquery-mobile.js来检测触摸屏事件,它适用于iOS, Android等,但我也想根据用户的设备是否有触摸屏来编写条件语句。
这可能吗?
当前回答
这个问题
由于混合设备使用触摸和鼠标输入的组合,你需要能够动态地改变状态/变量,控制一段代码是否应该运行,如果用户是触摸用户或不是。
触控设备也可以在点击时触发鼠标移动。
解决方案
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);
}
其他回答
更新:在将整个功能检测库拉入你的项目之前,请阅读下面blmstr的回答。检测实际的触摸支持更加复杂,Modernizr只涵盖了一个基本的用例。
Modernizr是一种很棒的轻量级方法,可以在任何网站上进行各种特征检测。
它只是为每个特性在html元素中添加类。
然后你可以在CSS和JS中轻松地瞄准这些功能。例如:
html.touch div {
width: 480px;
}
html.no-touch div {
width: auto;
}
和Javascript (jQuery示例):
$('html.touch #popup').hide();
关于如何在Javascript中检测页面是否显示在触摸屏设备上,我也遇到了很多困难。 在我看来,到目前为止,还没有真正的选项可以正确地检测这个选项。 浏览器要么报告桌面机器上的触摸事件(因为操作系统可能已经准备好触摸了),要么某些解决方案不能在所有移动设备上工作。
最后,我意识到我从一开始就采取了错误的方法: 如果我的页面在触摸和非触摸设备上看起来相似,我可能根本不需要担心检测属性: 我的方案是禁用触摸设备上的按钮上的工具提示,因为它们会导致双击,而我希望通过一次点击来激活按钮。
我的解决方案是重构视图,这样按钮上就不需要工具提示了,最后我也不需要用Javascript的方法来检测触摸设备了,因为这些方法都有自己的缺点。
有一种方法比检查他们是否拥有触摸屏更好,那就是检查他们是否正在使用触摸屏,而且这更容易检查。
if (window.addEventListener) {
var once = false;
window.addEventListener('touchstart', function(){
if (!once) {
once = true;
// Do what you need for touch-screens only
}
});
}
var isTouchScreen = 'createTouch' in document;
or
var isTouchScreen = 'createTouch' in document || screen.width <= 699 ||
ua.match(/(iPhone|iPod|iPad)/) || ua.match(/BlackBerry/) ||
ua.match(/Android/);
我想会进行更彻底的检查。
所以关于检测触摸/非触摸设备存在很大的争议。窗口平板电脑的数量和尺寸都在增加,这给我们网页开发者带来了另一个难题。
我已经使用并测试了blmstr的菜单答案。菜单的工作方式是这样的:当页面加载时,脚本检测这是一个触摸或非触摸设备。基于此,菜单将在悬停(非触摸)或点击/点击(触摸)时工作。
在大多数情况下,blmstr的脚本似乎工作得很好(特别是2018年的那个)。但仍然有一种设备,当它不是触摸时,它会被检测为触摸,反之亦然。
出于这个原因,我做了一些挖掘,多亏了这篇文章,我从blmstr的第4个脚本中替换了几行:
函数is_touch_device4() { If ("ontouchstart" in window) 返回true; 如果窗口。DocumentTouch的文档实例) 返回true; 返回窗口。matchMedia("(指针:粗)").matches; } alert('Is touch device: '+is_touch_device4()); console.log('Is touch device: '+is_touch_device4());
由于封锁,有有限的触摸设备来测试这一个,但到目前为止,上面的工作很好。
如果任何人有桌面触摸设备(如平板电脑)可以确认脚本是否工作正常,我将不胜感激。
现在在支持指针方面:粗媒体查询似乎是支持的。我保留了上面的行,因为我在移动firefox上(出于某种原因)出现了问题,但媒体查询上面的行是有效的。
谢谢