【问题标题】:How to detect if a device has mouse support?如何检测设备是否支持鼠标?
【发布时间】:2022-03-19 23:15:37
【问题描述】:

我目前使用以下测试(取自 Modernizr)来检测触摸支持:

function is_touch_device() {
    var bool;
    if(('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch) {
        bool = true;
    } else {
        injectElementWithStyles(['@media (',prefixes.join('touch-enabled),('),mod,')','{#modernizr{top:9px;position:absolute}}'].join(''), function(node) {
            bool = node.offsetTop === 9;
        });
    }
    return bool;
}

但有些设备是触摸和鼠标驱动的,所以我想要一个单独的函数来检测设备是否支持鼠标。进行此检查的好方法是什么?

最终我的意图是能够做到这些:

if(is_touch_device())

if(has_mouse_support())

if(is_touch_device() && has_mouse_support())

【问题讨论】:

  • 虽然它没有明确回答您的问题,但我发现这篇文章很有趣,涉及触摸与鼠标支持:html5rocks.com/en/mobile/touchandmouse
  • 未经测试(仅当鼠标实际移动时才有效): var mouse= false; window.onmousemove = function(){mouse= true}
  • @Reeno Clever,我认为这应该可行,但如果有人有已知的解决方案,将等待更经过测试的答案。编辑:这是真的,如果鼠标从不移动嗯,它会给出误报。
  • 如果有人从不摆动鼠标,他们可能更喜欢其他交互方式......
  • 嗯。根据html5rocks.com/en/mobile/touchandmouse/#toc-1 我的解决方案不起作用。该死:)关于这个话题的讨论很长:github.com/Modernizr/Modernizr/issues/869似乎没有一个好的解决方案

标签: javascript jquery


【解决方案1】:

a CSS media 就是为了这个!

您可以通过获取pointer CSS媒体功能的值来检查某些设备是否有鼠标:

if (matchMedia('(pointer:fine)').matches) {
  // Device has a mouse
}

因为它是 CSS 你甚至不需要使用 JavaScript:

@media (pointer: fine) {
  /* Rules for devices with mouse here */
}

【讨论】:

  • 太棒了,我认为这样的功能会很棒,但从不希望它真的存在!
  • 在装有 Firefox 的 Android 手机上不适合我。 (pointer: fine) 是匹配的,尽管没有指针设备。
  • 您的测试仅针对主设备。如果鼠标是某些内置设备(例如触摸输入)的附加设备,则它不起作用。您可以为此使用any-pointer,但Chrome 无法在选定数量的情况下支持此功能,例如在带有Win10 的敞篷车上,例如带有外接鼠标的Surface 设备。由于它的市场份额以及代表 Chrome 开发人员对这个 issue 的明显缺乏兴趣,这个功能完全没用。感谢 Google 将 Chrome 转变为下一个破坏网络的 MSIE 式 PITA。
【解决方案2】:

我目前正在使用以下(jQuery),我还没有在特定设备上发现任何缺陷

$(window).bind('mousemove.hasMouse',function(){
    $(window).unbind('.hasMouse');
    agent.hasMouse=true;
}).bind('touchstart.hasMouse',function(){
    $(window).unbind('.hasMouse');
    agent.hasMouse=false;
});

解释:鼠标设备(也包括触摸屏笔记本电脑)在触发 touchstart 之前首先触发 mousemove,并且 hasMouse 设置为 TRUE。触摸设备(例如触发 mousemove 的 iOS)在单击时首先触发 touchstart,然后触发 mousemove。这就是为什么 hasMouse 会被设置为 FALSE。

唯一的问题是这取决于用户交互,该值仅在鼠标移动或触摸启动后才正确,因此不能信任在页面加载时使用。

【讨论】:

  • $(window).one('mousemove',function(){agent.hasMouse=true}).one('touchstart',function(){agent.hasMouse=false});
【解决方案3】:

正如问题cmets中提到的,特别是https://github.com/Modernizr/Modernizr/issues/869,目前还没有好的答案。

【讨论】:

【解决方案4】:

@josemmo 的回答对我不起作用:在带有鼠标的 Android 手机上 matchMedia('(pointer:fine)').matches 不匹配。

幸运的是,我成功完成了另一个媒体查询:hover

if (matchMedia('(hover:hover)').matches) {
  // Device has a mouse
}

【讨论】:

  • 远非完美。根据上面的代码,我的手机(Galaxy S8+)有一个鼠标。是的,我很惊讶,但事实仍然存在。
  • 可能是因为三星 S Pen 支持
  • 很多智能手机都支持悬停,即使没有连接鼠标,所以这不是一个好的解决方案。我在裸机 OnePlus 3 上尝试过这个示例代码,它返回 true,而我没有鼠标。
【解决方案5】:
var clickHandler = (isMouseEventSupported('click') ? 'click' : 'touchstart');

function isMouseEventSupported(eventName) {
    var element = document.createElement('div');
    eventName = 'on' + eventName;
    var isSupported = (eventName in element);
    if (!isSupported) {
       element.setAttribute(eventName, 'return;');
       isSupported = typeof element[eventName] == 'function';
    }
    element = null;
    return isSupported;
}

这是我的朋友/同事的代码,他基于:http://perfectionkills.com/detecting-event-support-without-browser-sniffing/

【讨论】:

  • 我很确定所有的触摸设备都支持 onclick 事件...这并不意味着它们有鼠标。
【解决方案6】:

没有立即知道的方法,您必须等待触摸事件或鼠标事件。

假设您想要检测任一鼠标触摸,您可以执行以下操作:监听touchstartmousemove(后者可以在触摸设备上触发而无需一个真正的鼠标)。无论哪个先触发,99% 的结果都是您要找的。​​p>

这不考虑实际上同时具有两者的设备。

document.addEventListener('mousemove', onMouseMove, true)
document.addEventListener('touchstart', onTouchStart, true)
function onTouchStart(){
  removeListeners()
  // touch detected: do stuff
}
function onMouseMove(){
  removeListeners()
  // mouse detected: do stuff
}
function removeListeners(){
  document.removeEventListener('mousemove', onMouseMove, true)
  document.removeEventListener('touchstart', onTouchStart, true)
}

【讨论】:

    【解决方案7】:

    截至 2021 年,指针事件已在所有主要浏览器中实现。

    它使您可以动态检测指针设备鼠标、触摸和笔。

    var is_touch_device=(('ontouchstart' in window)||
                        (navigator.maxTouchPoints > 0)||
                        (navigator.msMaxTouchPoints > 0));
    
    var has_mouse_support=false;
    document.addEventListener("pointermove", function(evt) {
      var pointerType=evt.pointerType;
      /*** Safari quirk  ***/
      if(pointerType==="touch"&&evt.height===117.97119140625
                             &&evt.height===evt.width)pointerType="mouse";
      /*** Safari quirk  ***/
      has_mouse_support=(pointerType==="mouse");
    }
    

    这当然取决于用户移动鼠标指针。

    如果激活了 AssistiveTouch,即使 ipadOS 14.4.2 上的 safari 也会检测到它!但是那里的指针类型检测似乎有些怪癖。它在第一次使用鼠标并且没有执行触摸时将指针类型检测为鼠标。但是如果你以后使用触摸,它不会检测并更改为鼠标的指针类型,如果在触摸后使用鼠标!毫不奇怪!

    编辑:在玩弄了 ipadOS safari 之后,我发现,当鼠标在触摸后使用时,pointerevent 的宽度和高度完全相同,在 ipadOS 14.4.2 中是 117.97119140625 每个使用鼠标的时间。这可以用作不可靠的解决方法。谁知道他们什么时候会改变宽度/高度? ipadOS 中指针移动检测的另一个特点是,鼠标移动仅在按下鼠标按钮时才会检测到。

    未在 ipad/iphone 上使用笔进行测试。谁知道这会显示出哪些怪癖?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-07-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-25
      • 1970-01-01
      • 2011-06-06
      • 2013-11-27
      相关资源
      最近更新 更多