2020 年使用 JavaScript 检测触摸设备并检测“可以悬停”

Zet*_*eth 5 javascript

TL;DR 版本

如何使用普通 JavaScript 检查用户是否在触摸设备上和/或可以悬停?


详细版

这篇文章提出了无数种不同的方法来解决这个问题。但现在已经是 2020 年了,浏览器和设备上发生了很多事情,所以我想我应该划清界限并开始一个新问题。许多答案没有考虑所有极端情况:

  • 就像手写笔一样
  • 就像苹果的神奇鼠标(显然)模拟触摸事件(我听说过这个,我自己没有体验过)。
  • 就像新的 iPad Pro 一样,它模拟了 Macbook Pro 的 Safari。
  • 就像功能发生变化一样,用户获得/失去“触摸”的能力(就像使用 Chrome 开发者工具启用移动视图时一样)。

我的发现

不要使用window.matchMedia('(any-pointer: XXXXX)').matches

window.matchMedia一些答案表明“新奇” any-pointer: coarse|none|fine。然而,我很幸运,我有一部 OnePlus 5t。因为 matchMedia 在我的设备上的 Firefox 和 Chrome 中都不起作用(错误匹配)。我尝试了 A TON,因为我希望有相同的 CSS 检查,所以我的 JavaScript 和 CSS 相互对应,确保样式和功能匹配。

不要使用 userAgent 匹配

这不是一个好主意,因为每次新浏览器出现时都需要维护 userAgent 列表。因此,这样做并不能保证未来的发展。就像前面提到的 iPad Pro 示例一样。

不要使用人类接触

这篇 Code Burst 文章建议使用人体触摸而不是检测设备触摸。这可能是解决方案的一部分。但是,如果我有一个供触摸用户使用的菜单,那么我必须立即显示该菜单,而不是等待用户触摸屏幕后再显示。

Zet*_*eth 9

我制作了一个 CodePen,它已准备好添加新功能,并轻松测试我。它还显示了迄今为止我找到的最佳解决方案: https: //codepen.io/zethzeth/pen/yLewqbg

我不知道如何处理手写笔或其他奇怪的情况。

这是函数:

function is_touch_device4(){
  return window.matchMedia('(hover: none)').matches;
}
Run Code Online (Sandbox Code Playgroud)