Javascript 如何检测设备是否支持鼠标?

Javascript 如何检测设备是否支持鼠标?,javascript,jquery,Javascript,Jquery,我目前使用以下测试(从Modernizer中取出)来检测触摸支持: function is_touch_device() { var bool; if(('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch) { bool = true; } else { injectElementWithStyles([

我目前使用以下测试(从Modernizer中取出)来检测触摸支持:

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())

正如问题评论中提到的,特别是关于,还没有很好的答案。

我目前正在使用以下(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

唯一需要注意的是,这取决于用户交互,该值只有在鼠标移动或触摸启动后才正确,因此无法信任在页面加载时使用

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;
}

这是我的一位朋友/同事的代码,他根据以下内容编写:

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

假设您想要检测鼠标或触摸,您可以执行以下操作:监听
touchstart
mousemove
(后者可以在没有实际鼠标的触摸设备上启动)。无论谁先开火,99%都是你要找的

这并不考虑实际同时具有这两种功能的设备

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)
}
就为了这个

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

if (matchMedia('(pointer:fine)').matches) {
  // Device has a mouse
}
因为它是CSS,所以您甚至不需要使用JavaScript:

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

@josemo的回答对我不起作用:在安卓手机上,鼠标连接
matchMedia('(指针:精细)')。匹配的
不匹配

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


截至2021年,pointerevents已在所有主要浏览器中实现

它使您能够动态检测鼠标、触摸和笔等指针设备

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");
}
当然,这取决于用户移动鼠标指针

即使ipadOS 14.4.2上的safari也会检测到它,如果激活了AssistiveTouch!但这里的指针类型检测似乎有一些怪癖。首次使用鼠标且未执行任何触摸时,它会将pointerType检测为鼠标。但如果您以后使用触摸,它将不会检测并更改为鼠标指针类型,如果触摸后使用鼠标!不足为奇

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


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

虽然这篇文章没有明确回答您的问题,但我发现这篇文章很有趣:wrt touch vs.mouse support:Untested(仅当鼠标实际移动时有效):var mouse=false;window.onmousemove=function(){mouse=true}@Reeno-cleen,我认为这应该可以,但将等待更可靠的答案,以防有人知道解决方案。编辑:这是真的,如果鼠标从未移动,它将给出假阳性。如果有人从未晃动过鼠标,他们可能更喜欢其他交互方式…嗯。根据我的说法,解决方案不起作用。该死:)这是一个关于这个话题的长时间讨论:似乎没有一个好的解决方案。我真的只是把这个作为一个答案,以便“正式”标记为一个副本。那么,检查“window.MouseEvent”是否如建议的那样存在呢?@DesignbyAdrian转述自:平板电脑的不一致行为,特别是iPad和Surface我很确定所有触摸设备都支持onclick事件。。。这并不意味着他们有鼠标。$(窗口)。一个('mousemove',function(){agent.hasMouse=true})。一个('touchstart',function(){agent.hasMouse=false});太棒了,我以为这样的功能会很棒,但我从来没希望它真的存在!不适合我在Android手机上使用Firefox<代码>(指针:很好)
是一个匹配,尽管没有指针设备。远非完美。根据上面的代码,我的手机(Galaxy S8+)有一个鼠标。是的,我很惊讶,但事实依然如此。这可能是因为三星的笔支持很多智能手机都支持悬停,即使没有连接鼠标,所以这不是一个好的解决方案。我在一个裸的OnePlus 3上尝试了这个示例代码,结果返回true,而我没有鼠标。
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");
}