Javascript 在触摸屏设备上检测鼠标

Javascript 在触摸屏设备上检测鼠标,javascript,jquery,touch,Javascript,Jquery,Touch,我使用以下代码检测设备是否为触摸设备: var isTouchDevice = 'ontouchstart' in window || navigator.msMaxTouchPoints; if(isTouchDevice) { $('body').addClass('yes-touch'); } else { $('body').addClass('no-touch'); } 我使用此选项仅显示非触摸设备时的:hover状态(因为大多数触摸设备将点击理解为悬停) 问题是,

我使用以下代码检测设备是否为触摸设备:

var isTouchDevice = 'ontouchstart' in window || navigator.msMaxTouchPoints;

if(isTouchDevice)
{
    $('body').addClass('yes-touch');
}
else
{
    $('body').addClass('no-touch');
}
我使用此选项仅显示非触摸设备时的
:hover
状态(因为大多数触摸设备将点击理解为悬停)

问题是,我们办公室的一台电脑是一台全合一触摸屏电脑,这意味着使用鼠标时不会出现悬停状态


有没有办法确定鼠标是否在触摸屏设备上使用?换句话说,当使用鼠标时,它应该应用
禁止触摸
类,而当使用触摸屏时,它应该应用
是触摸
类。

到目前为止,还没有简单可靠的方法。现代人,几乎是特征检测方面的专家,最近对此有这样的看法:

所有这一切的最终结果是,您无法在中检测到鼠标的使用 一种符合Modernizer可靠性水平的方法 归功于。就我们的意图和目的而言,这是一个无法察觉的问题

如果您,未来的旅行者,希望尝试检测鼠标用户,那么 以下是我能提供的最好的指南

  • 不要。认真地仅仅因为用户有一个“鼠标”并不意味着这一点 他们没有其他多种形式的输入。你真的应该试试 很难避免做出任何基于更改的UI/UX决策 一个鼠标用户与一个 触摸屏用户(或任何其他类型的用户)。制造东西 普遍的
  • 如果你不得不,只关心IE 10和11,那么IE PointerEvent值得一看。外界的支持非常糟糕 这两个版本中的一个(可能是未来的IE版本)
  • 您可以附加一个 主体上的“悬停”事件的侦听器,如果为true,则 用户可能有鼠标。这种方法的缺点包括 触摸事件在轻触/触摸时短暂触发悬停事件,因此您可以 得到假阳性
  • 嗅探移动用户代理。这是个坏主意, 与现代化的核心背道而驰。请不要这样做
  • 因此,对我来说,我几乎是对它的总结。然而,这回答了你的问题,但没有给你一个解决方案。您提到“办公室中的一台我们的电脑…”这是一个偶然的内部应用程序吗?我偶尔会遇到这样的情况,即内部特殊用途或一次性页面可能出于任何原因需要一些单独的处理(例如我们的一名员工使用带有鼠标的触摸式AIO)。然后,我要做的是在url的末尾附加一个
    ?hasmouse
    ,并为用户提供指向书签的链接。然后,在javascript中,在您的设备之后,但在您的if之前,插入以下代码以撤销它:

    if (location.search == '?hasmouse') {
        isTouchDevice = false;
    }
    

    再说一次,这是一种只供内部使用的简单方法。

    到今天为止,还没有简单可靠的方法。现代人,几乎是特征检测方面的专家,最近对此有这样的看法:

    所有这一切的最终结果是,您无法在中检测到鼠标的使用 一种符合Modernizer可靠性水平的方法 归功于。就我们的意图和目的而言,这是一个无法察觉的问题

    如果您,未来的旅行者,希望尝试检测鼠标用户,那么 以下是我能提供的最好的指南

  • 不要。认真地仅仅因为用户有一个“鼠标”并不意味着这一点 他们没有其他多种形式的输入。你真的应该试试 很难避免做出任何基于更改的UI/UX决策 一个鼠标用户与一个 触摸屏用户(或任何其他类型的用户)。制造东西 普遍的
  • 如果你不得不,只关心IE 10和11,那么IE PointerEvent值得一看。外界的支持非常糟糕 这两个版本中的一个(可能是未来的IE版本)
  • 您可以附加一个 主体上的“悬停”事件的侦听器,如果为true,则 用户可能有鼠标。这种方法的缺点包括 触摸事件在轻触/触摸时短暂触发悬停事件,因此您可以 得到假阳性
  • 嗅探移动用户代理。这是个坏主意, 与现代化的核心背道而驰。请不要这样做
  • 因此,对我来说,我几乎是对它的总结。然而,这回答了你的问题,但没有给你一个解决方案。您提到“办公室中的一台我们的电脑…”这是一个偶然的内部应用程序吗?我偶尔会遇到这样的情况,即内部特殊用途或一次性页面可能出于任何原因需要一些单独的处理(例如我们的一名员工使用带有鼠标的触摸式AIO)。然后,我要做的是在url的末尾附加一个
    ?hasmouse
    ,并为用户提供指向书签的链接。然后,在javascript中,在您的设备之后,但在您的if之前,插入以下代码以撤销它:

    if (location.search == '?hasmouse') {
        isTouchDevice = false;
    }
    

    同样,对于内部使用来说,这是一种没有装饰的方式。

    我已经使用了一段时间,它似乎工作可靠。有时,如果值得的话,我会很伤心,但这确实有效

    这里的想法是捕获实际触地事件以触发触地模式,并使用mousemove触发鼠标模式。问题是IE不会触发触摸事件,而是指针事件。指针事件的好处在于,你可以检查它是鼠标还是触摸

    问题是,所有其他浏览器在触摸事件之后都会触发一个假的mousemove。真让人发疯

    你可以看到它在这方面起作用

    //首先检查这是否是触摸设备:

    this.isTouch = 'ontouchstart' in window || (navigator.msMaxTouchPoints > 0);
    
    //我们以后需要一些VAR

    var lastTouch = 0
    var lastCheck = 0
    
    //然后设置事件侦听器:

    function initEvents() {
    
      //handle touch/mouse devices detect mouse so that touch is toggled off
      if (this.isTouch) {
    
        $(document).on(" touchstart mousemove " + msPointerEvent('move'), function(e) {
          e = e.originalEvent
            //browser has pointer events
          var pe = window.PointerEvent || window.MSPointerEvent
    
          // handle ie pointer events (polyfill functions are at bottom of answer)
    
          if (e.type == msPointerEvent('move')) {
            var touchEvent = msPointerType(e) == 'touch'
            if (touchEvent)
              lastTouch = e.timeStamp;
            if (!this.isTouch && touchEvent)
              return setupTouch.call(this, true)
            else if (this.isTouch && !touchEvent)
              return setupTouch.call(this, false)
          }
    
          // Handle all other browser touch events
          if (e.type == "touchstart") {
            console.log('touchstart fired')
            lastTouch = e.timeStamp;
            if (!this.isTouch)
              setupTouch.call(this, true);
          }
    
          // test mouse move and set up mouse mode if real
          else if (!pe && e.type == "mousemove" && this.isTouch) {
            if (realMouseDown.call(this, e)) {
              setupTouch.call(this, false)
            }
          }
        }.bind(this));
      }
    }
    initEvents()
    
    //这就是我们变得聪明的地方。事实证明,假mousemove将在不到500毫秒的触摸时间内启动,因此我们使用它来检测假货。然后当然为IE做一些特别的事情:

    function realMouseDown(e) {
    
      var touchDif = e.timeStamp - lastTouch
      var mouseDif = e.timeStamp - lastCheck
    
      // false mouse event will get fired within 500ms of a touch (touchDif > 500)
      // (required for all browsers false mouse after touch event)
      var real = touchDif > 500
    
      lastCheck = e.timeStamp;
      console.log('real=', real, ' mDif ='+mouseDif, ' tDif ='+touchDif)
    
      return real
    }
    

    // IE pointer event polyfill function msPointerEvent(type) { var n = "" if (window.PointerEvent) // IE 11 n = 'pointer' + type else if (window.MSPointerEvent) // IE 10 n = 'MSPointer' + type[0].toUpperCase() + type.substr(1); return n } // IE pointer type polyfill function msPointerType(e) { var pt = ['zero', 'one', 'touch', 'pen', 'mouse'] return typeof e.pointerType == 'string' ? e.pointerType : pt[e.pointerType] }

    // make required changes for touch / mouse
    var $output = $('#output')
    function setupTouch(state) {
      console.log('TouchMode=', state)
      if (state)
        this.isTouch = true
      else
        this.isTouch = false
      $output.html('Touch mode changed to = '+state)
    
    }