【问题标题】:How do I detect whether a browser supports mouseover events?如何检测浏览器是否支持鼠标悬停事件?
【发布时间】:2011-06-06 07:39:27
【问题描述】:

假设我有一个网页,它有一些 onmouseover javascript 行为来下拉菜单(或类似的东西)

显然,这不适用于 iPad 或智能手机等触控设备。

如何检测浏览器是否支持 onmouseover 或 onmouseout 等悬停事件以及 CSS 中的 :hover 伪标签?

注意:我知道如果我担心这个我应该写一个不同的方式,但我很好奇是否可以进行检测。

编辑:当我说“支持悬停事件”时,我的真正意思是“浏览器是否具有悬停事件的有意义表示”。如果硬件支持但软件不支持(反之亦然),则没有有意义的表示。除了一些 upcoming tech 之外,我认为没有任何触摸设备能够有意义地表示悬停事件。

【问题讨论】:

  • 我认为您的问题需要重新表述,因为 iPad 在理论上确实支持悬停,但输入使其成为不可能。所以你的问题应该是:我如何检测用户是否有可能将鼠标悬停在一个项目上?
  • 也许这可以给你一个开始:stackoverflow.com/questions/3974827/…
  • @nightcracker - 从网站(和我)的角度来看,硬件是否能够支持悬停并不重要 - 唯一重要的是是否有有意义的 onmouseover 或onmouseout 钩子。我会在问题中澄清。
  • @amosriviera - 谢谢你,这个问题中有一些有趣的东西。有一个答案可以让我选择 iPad,但没有跨浏览器。

标签: javascript html touch onmouseover browser-detection


【解决方案1】:
var supportsTouch = (typeof Touch == "object");

只需检测它是否是触摸设备,然后执行您的特殊操作。 这是最简单的方法,因为大多数触摸设备模拟鼠标事件,但没有鼠标驱动的设备模拟触摸事件。

更新:考虑到现在一天有多少台设备和Johan 的cmets,我建议直接使用Modernizr

【讨论】:

  • 这适用于所有/大多数触控设备吗? Android 手机和平板电脑、诺基亚触摸屏以及 iWhatevers?
  • Android 和 iThings 99.9%,Symbian?是的,从某些 QtWebKit 版本开始,但不要问我会是哪个版本的 Symbian。
  • 您在寻找替代品吗?考虑 onmousemove 但这将需要超时,并且可能最终会在某些平台上被模拟。
  • 应该注意的是,支持触摸事件的设备不一定是悬停挑战的:它们可能支持不止一种与之交互的方式(例如,笔)。
  • Surface 平板电脑上的 IE10 和 11 不支持触​​摸事件,即使 Surface 是触摸设备。
【解决方案2】:

此方法捕获更多设备/浏览器

try {
   document.createEvent("TouchEvent");
   alert(true);
}
catch (e) {
   alert(false);
}

Read more

【讨论】:

  • 在我一直在测试的机器人中,我根本没有得到公认的答案,但这个很好用。
  • 接受的答案对我也没有任何作用,但这一个成功了!谢谢,约翰。
  • 最新版 Chrome(v. 32,Win7,无触摸屏)的误报。
【解决方案3】:

现在是 2016 年,很多设备都具备触控和类似鼠标的输入功能已经有好几年了。 “不能触摸”不是判断“可以鼠标悬停”的好方法。仅举几个例子:

  • "Active pen" digitizer devices 喜欢 Galaxy Note 手机和平板电脑 (Android)、Microsoft Surface (Windows) 和 Wacom Cintiq (Mac/Windows/Android),我也相信 iPad Pro,它的笔像鼠标一样工作并且可以“空中悬停”距离屏幕约 1 厘米时
  • 带有触摸屏的 Windows 笔记本电脑/混合型笔记本​​电脑以及传统笔记本电脑触控板等
  • 可连接到任何 PC 并与鼠标一起使用的触摸屏显示器

因此用户可能无法将鼠标悬停一分钟,然后,在同一设备上,不刷新页面,他们将笔从 Galaxy Note 中拔出,然后(假设它不会着火)他们突然 在他们的交互中使用悬停,他们希望它能够正常工作。


如果您需要知道您的用户是否 a)可以使用和 b)当前正在使用能够让他们方便地移动鼠标的设备,强> 你可以:

  • 如果触发鼠标移动的光标正在移动,则将mousemove 事件绑定到您的文档body 以激活“悬停”状态(例如,将类user-can-mouseover 添加到body),然后立即解除自身绑定所以它只会发生一次。
  • 还绑定一个 touchstart 事件以暂时停用 mousemove 和一个 touchend 以重新激活它,这样,在触发鼠标触摸事件的浏览器上(在 Android 和 Windows 上很常见),正常的触摸滚动不会不要触发mousemove
  • mousemove 事件取消绑定这些 touchstarttouchend 事件以进行良好的内务管理

这将导致在用户开始使用行为类似于鼠标的输入设备时触发“可以悬停”状态。


以混合设备为例:

  1. 最初,用户使用触摸和滑动浏览网页。
  2. 他们到达您的应用程序,使用触摸上下滑动,同时了解它是什么。到目前为止,“可以悬停”条件尚未激活。
  3. 他们认为这是他们想要比他们的胖手指更精确的情况之一,因此他们拔出数字化笔或伸手去拿鼠标。
  4. 这会导致光标在页面上移动而不会发生未结束的触摸事件,因此会触发“可以悬停”条件

...用鼠标拿一个老式的桌面工作站:

  1. 页面加载。
  2. 用户在做任何事情时移动鼠标,立即触发鼠标移动事件
  3. 立即触发“可以悬停”状态

【讨论】:

    【解决方案4】:

    基于 user568458 的响应的一组函数,允许您打开/关闭触摸设备的 :hover 样式(我还没有在所有设备上尝试过):

    function detectMouseMove() {
        $(document).one('mousemove', function() { 
            $('body').addClass('hoverActive');
            detectTouchEvent();
        });
    }
    function detectTouchEvent() {
        $(document).one('touchstart', function() { 
            $('body').removeClass('hoverActive');
            detectMouseMove();
        });
    }
    

    然后您可以在样式表中的任何 :hover 选择器之前使用 .hoverActive 来防止移动浏览器尝试显示悬停状态。

    【讨论】:

      【解决方案5】:

      non-legacy browsers 的另一种方法是利用媒体查询 hoverany-hover

      matchMedia('(hover: hover)').matches; // Primary device can hover
      
      matchMedia('(hover: none)').matches; // Primary device cannot hover
      
      matchMedia('(any-hover: hover)').matches; // At least one of the connected devices can hover
      
      matchMedia('(any-hover: none)').matches; // None of the connected devices can hover
      

      【讨论】:

      • 很好的答案。我刚刚在三星 Galaxy Note 8 上进行了尝试,链接的“悬停”示例与笔完美配合(悬停时为黄色),但“任意悬停”没有(悬停时没有响应)。很奇怪,因为如果笔是触控后的辅助输入法,我会期望它是相反的吗?
      猜你喜欢
      • 1970-01-01
      • 2017-05-17
      • 1970-01-01
      • 2011-06-24
      • 2013-06-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多