【问题标题】:How can I detect device touch support in JavaScript?如何检测 JavaScript 中的设备触摸支持?
【发布时间】:2013-01-21 13:38:01
【问题描述】:

过去,当检测设备是否支持 JavaScript 中的触摸事件时,我们可以这样做:

var touch_capable = ('ontouchstart' in document.documentElement);

但是,即使底层设备不支持触摸事件,谷歌浏览器 (17.x.x+) 也会返回 true 进行上述检查。例如,在 Windows 7 上运行上述代码会返回 true,因此如果我们将其与以下内容结合使用:

var start_evt = (touch_capable) ? 'ontouchstart' : 'onmousedown';

在 Google Chrome 上,由于我们绑定到 ontouchstart,因此永远不会触发该事件。简而言之,有没有人知道一种可靠的方法来规避这个问题?我目前正在运行以下检查:

var touch_capable = ('ontouchstart' in document.documentElement && navigator.userAgent.toLowerCase().indexOf('chrome') == -1)

这远非理想......

【问题讨论】:

    标签: javascript google-chrome dom-events


    【解决方案1】:

    正确的答案是处理两种事件类型——它们不是相互排斥的。

    要获得更可靠的触摸支持测试,还可以查找window.DocumentTouch && document instanceof DocumentTouch,这是Modernizr 使用的测试之一

    更好的是,您只需自己使用 Modernizr 并让它为您进行特征检测。

    请注意,尽管您无法防止误报,因此我上面的第一行 - 您已经 得到 支持两者。

    【讨论】:

    • 正确 - 虽然我有(并且喜欢)平板电脑,但有时我有鼠标而且我并不害怕使用它。
    • 谢谢。这实际上是一个 jQuery 插件,我也不想添加 Modernizr 的先决条件。但是,由于某种原因,window.DocumentTouch && document instanceof DocumentTouch 返回undefined...
    • @BenM 你知道可以构建一个只包含你需要的测试的自定义下载 Modernizr 吗?
    • 是的,我愿意。但是,如果您查看它们在 Modernizr 中执行的测试(即('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch),那么 Chrome 17.x.x+ 将返回 true,因为第一次评估是真的......
    • @BenM "undefined" 是桌面 Chrome 上该测试的预期结果。看看我链接到的 Modernizr 源模块。
    【解决方案2】:

    这是对 Modernizr 执行触摸检测方式的修改,增加了对 IE10+ 触摸设备的支持。

    var isTouchCapable = 'ontouchstart' in window ||
     window.DocumentTouch && document instanceof window.DocumentTouch ||
     navigator.maxTouchPoints > 0 ||
     window.navigator.msMaxTouchPoints > 0;
    

    自从detecting a touch device is apparently an impossibility之后就不是万无一失了。

    您的里程可能会有所不同:

    • 较旧的触摸屏设备仅模拟鼠标事件
    • 某些浏览器和操作系统设置可能会在未连接触摸屏时启用触摸 API,例如,在安装了触摸屏驱动程序但触摸硬件不起作用或未安装的系统中。
    • 在混合鼠标/触摸/触控板/笔/键盘环境中,这并不表示正在使用哪个输入,仅表示浏览器检测到存在触摸硬件。例如,用户可以随时从使用鼠标切换到触摸支持触摸的笔记本电脑或连接鼠标的平板电脑上的屏幕。它只检测浏览器是否认为它可以接受或模拟触摸输入,例如,在 Chrome 开发工具中使用移动模拟模式时。

    更新: 提示:不要使用触摸功能检测来控制和指定 UI 行为,use event listeners instead。为点击/触摸/按键事件设计,而不是设备,触摸功能检测通常用于节省添加事件侦听器的 CPU/内存开销。触摸检测可能有用且合适的一个示例:

    if (isTouchCapable) {
        document.addEventListener('touchstart', myTouchFunction, false); 
    }
    

    【讨论】:

    • 为我工作,谢谢!
    • @Benson:谢谢!这适用于大多数浏览器,但我注意到它不适用于 Windows 10 上的 Chrome 65.0.3325.181。使用 Lenovo Thinkpad T460(非触摸屏)时,该语句返回 true。
    • @user2718671 我在 Windows 10 上使用 Chrome 65 的非触摸屏笔记本电脑对此进行了测试。我可以让它报告该设备具有触摸功能的唯一方法是,如果我对移动设备使用设备仿真设备。当您打开 Chrome Inspector 时,请检查您的光标是否是“箭头”而不是“手指阴影”点,以确保您没有处于触摸模拟模式。
    • @Benson:是的,我知道。未启用触摸模拟。也许这只是一个特例。我认为这是因为还有一个带触摸屏的联想 Thinkpad T460,只是一些驱动程序或一些隐藏的硬件组件让 Chrome 认为它是一个触摸屏。无论如何,这真的很奇怪:D
    • @user2718671 明白了。我猜这是 Chrome 报告的第一个声明 "ontouchstart" in window 是真的?也许有一些touch属性证明它不是,实际上touch能够防止误报,我们可以将它添加到逻辑链中。如果您发现该属性可能是什么,请分享。
    【解决方案3】:

    您应该考虑使用经过良好测试(和跨浏览器)的 Modernizr 的触摸测试。

    来自他们的网站:

    // bind to mouse events in any case
    
    if (Modernizr.touch){
       // bind to touchstart, touchmove, etc and watch `event.streamId`
    } 
    

    http://modernizr.github.com/Modernizr/touch.html

    【讨论】:

    • 正确的情绪,错误的答案。 Modernizr 可以测试触摸支持的“误报”,因此您仍然应该始终支持鼠标事件。
    • 除此之外,强制用户使用他们的触摸屏(而不是他们持有的鼠标)是不好的。
    • 是的,应该始终包括鼠标支持,如果设备支持,还应该包括触摸支持。需要更正我的答案。
    【解决方案4】:

    老问题,但不得不在没有库的情况下执行此操作,我创建了以下解决方案——只需让事件自己说话——当您看到 touch 事件时,只需禁用 @987654322 的处理@事件。

    在 coffescript 中是这样的;

               hasTouch = false
               mouseIsDown = false
               @divs.on "touchstart", (e)->
                  hasTouch = true
                  touchstart(e.timeStamp,e.originalEvent.touches[0].pageX);
                  return true
               @divs.on "mousedown", (e)->
                  mouseIsDown = true;
                  touchstart(e.timeStamp,e.clientX) if not hasTouch
                  return true
    
               @divs.on 'touchmove', (e) ->
                  touchmove(e.timeStamp,e.originalEvent.touches[0].pageX);
                  return true;
               @divs.on 'mousemove', (e) ->
                  touchmove(e.timeStamp,e.clientX) if mouseIsDown and not hasTouch 
                  return true;
    
               @divs.on 'touchend', (e) ->
                  touchend();
                  return true
               @divs.on 'mouseup', (e) ->
                  mouseIsDown = false;
                  touchend() if not hasTouch
                  return true
    

    touchstartmoveend 的刚刚定义函数包含实际逻辑......

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-04-27
      • 1970-01-01
      • 2019-10-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多