检测到浏览器没有鼠标且仅限触摸

2022-08-30 02:00:07

我正在开发一个Web应用程序(不是一个包含有趣文本页面的网站),它具有非常不同的触摸界面(单击时手指会隐藏屏幕)和鼠标(严重依赖悬停预览)。如何检测我的用户没有鼠标来向他展示正确的界面?我计划为同时具有鼠标和触摸功能(如某些笔记本电脑)的人留下一个开关。

浏览器中的触摸事件功能实际上并不意味着用户正在使用触摸设备(例如,Modernizr 不会削减它)。如果设备有鼠标,则正确回答问题的代码应返回 false,否则返回 true。对于具有鼠标和触摸功能的设备,它应该返回 false(不仅仅是触摸)

顺便说一句,我的触摸界面可能也适用于仅键盘设备,因此更多的是我想要检测的鼠标不足。

为了使需求更加清晰,以下是我想要实现的API:

// Level 1


// The current answers provide a way to do that.
hasTouch();

// Returns true if a mouse is expected.
// Note: as explained by the OP, this is not !hasTouch()
// I don't think we have this in the answers already, that why I offer a bounty
hasMouse();

// Level 2 (I don't think it's possible, but maybe I'm wrong, so why not asking)

// callback is called when the result of "hasTouch()" changes.
listenHasTouchChanges(callback);

// callback is called when the result of "hasMouse()" changes.
listenHasMouseChanges(callback);

答案 1

截至2018年,有一种良好而可靠的方法来检测浏览器是否具有鼠标(或类似的输入设备):CSS4媒体交互功能现在几乎受到任何现代浏览器(IE 11和特殊移动浏览器除外)的支持。

W3C:

指针媒体功能用于查询指针设备(如鼠标)的存在和准确性。

请参阅以下选项:

    /* The primary input mechanism of the device includes a 
pointing device of limited accuracy. */
    @media (pointer: coarse) { ... }
    
    /* The primary input mechanism of the device 
includes an accurate pointing device. */
    @media (pointer: fine) { ... }
    
    /* The primary input mechanism of the 
device does not include a pointing device. */
    @media (pointer: none) { ... }

    /* Primary input mechanism system can 
       hover over elements with ease */
    @media (hover: hover) { ... }
    
    /* Primary input mechanism cannot hover 
       at all or cannot conveniently hover 
       (e.g., many mobile devices emulate hovering
       when the user performs an inconvenient long tap), 
       or there is no primary pointing input mechanism */
    @media (hover: none) { ... }
    
    /* One or more available input mechanism(s) 
       can hover over elements with ease */
    @media (any-hover: hover) { ... }
    
    
    /* One or more available input mechanism(s) cannot 
       hover (or there are no pointing input mechanisms) */
    @media (any-hover: none) { ... }

媒体查询也可以在 JS 中使用:

if(window.matchMedia("(any-hover: none)").matches) {
    // do something
}

相关:

W3 文档:https://www.w3.org/TR/mediaqueries-4/#mf-interaction

浏览器支持:https://caniuse.com/#search=media%20features

类似问题:检测客户端设备是否支持 :hover 和 :focus 状态


答案 2

主要问题是您有以下不同类别的设备/用例:

  1. 鼠标和键盘(桌面)
  2. 仅触摸(手机/平板电脑)
  3. 鼠标、键盘和触摸(触摸便携式计算机)
  4. 触摸和键盘(平板电脑上的蓝牙键盘)
  5. 仅限鼠标(已禁用的用户/浏览首选项)
  6. 仅键盘(禁用的用户/浏览首选项)
  7. 触摸和鼠标(即Galaxy Note 2笔中的悬停事件)

更糟糕的是,人们可以从其中一些类过渡到其他类(插入鼠标,连接到键盘),或者用户可能看起来像是在普通的笔记本电脑上,直到他们伸出手触摸屏幕。

您正确地假设浏览器中事件构造函数的存在不是继续前进的好方法(并且它有些不一致)。此外,除非您正在跟踪非常具体的事件或仅尝试排除上面的几个类,否则使用事件本身并不是完全证明。

例如,假设您发现用户发出了真正的鼠标移动(不是触摸事件中的错误鼠标移动,请参阅 http://www.html5rocks.com/en/mobile/touchandmouse/)。

然后呢?

是否启用了悬停样式?你添加更多按钮?

无论哪种方式,您都在增加玻璃的时间,因为您必须等待事件触发。

但是,当您的高贵用户决定要拔下鼠标并进行完全触摸时,会发生什么。你是否等着他触摸你现在塞满的界面,然后在他努力查明你现在拥挤的UI后立即更改它?

以子弹形式,在 https://github.com/Modernizr/Modernizr/issues/869#issuecomment-15264101 引用stucox

  • 我们想要检测鼠标的存在
  • 在触发事件之前,我们可能无法检测到它
  • 因此,我们检测到的是,如果在此会话中使用了鼠标 - 它不会立即从页面加载中
  • 我们可能也无法检测到没有鼠标 - 在true之前它是未定义的(我认为这比在证明之前将其设置为假更有意义)
  • 而且我们可能无法检测到鼠标是否在会话中途断开连接 - 这与用户只是放弃鼠标无法区分。

顺便说一句:浏览器确实知道用户何时插入鼠标/连接到键盘,但不会将其公开给JavaScript。当!

这应该会引导您执行以下操作:

跟踪给定用户的当前功能是复杂的,不可靠的,并且价值可疑

不过,渐进式增强的想法在这里非常适用。构建无论用户上下文如何都能顺利运行的体验。然后根据浏览器功能/媒体查询进行假设,以添加在假定上下文中相对的功能。鼠标的存在只是不同设备上的不同用户体验您网站的众多方式之一。创建一些有价值的东西,不要太担心人们如何点击按钮。