首页 > 解决方案 > 如何在桌面浏览器中从触控板上捕获捏缩放手势(并防止默认)?

问题描述

如果您在带有触控板的笔记本电脑上的 Chrome/Firefox 中打开谷歌地图,如果您捏缩放,它只会缩放地图,而浮动的 UI 元素保持静态。所以我知道我想做的事情是可能的。

浏览器似乎不会touch*为桌面浏览器上的触控板触摸发出事件,但它确实会为触控板捏缩放手势发出一系列wheel事件(event.ctrlKey设置为true)。

问题是,即使使用event.preventDefault(),浏览器仍然总是缩放整个页面。似乎调用preventDefault()事件wheel只是在控制台中打印此警告(Chrome 92):

[Intervention] Unable to preventDefault inside passive event listener due to target being treated as passive. See https://www.chromestatus.com/features/6662647093133312`

(警告中的 URL 似乎没有任何用处。)

我尝试使用与谷歌地图 ( ) 相同的元视口标签,<meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">但它没有帮助。

那么谷歌地图是如何做到的呢?当您在触控板上捏缩放时,它们如何防止默认行为(缩放整个页面)?

标签: javascript

解决方案


我手头没有触控板,但既然你说wheel事件是被触发的,我假设使用鼠标滚轮的上下文是相同的。

TL; 博士

调用addEventListener()with{passive: false}作为它的第三个参数就可以了。

即:

window.addEventListener('wheel', function(e) {

  e.preventDefault()
  ...

}, {passive: false})

解释

addEventListener()文档中,该passive选项的描述指出:

一个布尔值,如果为真,则表示侦听器指定的函数永远不会调用 preventDefault()。如果被动侦听器确实调用了 preventDefault(),则用户代理只会生成控制台警告。

根据同一页面中标题为“使用被动侦听器提高滚动性能”的部分:

根据规范,被动选项的默认值始终为 false。但是,这引入了事件侦听器处理某些触摸事件(以及其他事件)在尝试处理滚动时阻塞浏览器主线程的可能性,从而导致滚动处理期间的性能可能大大降低。

为防止出现此问题,某些浏览器(特别是 Chrome 和 Firefox)已将文档级节点 Window、Document 和 Document.body 上的 touchstart 和 touchmove 事件的被动选项的默认值更改为 true。这可以防止调用事件侦听器,因此它不能在用户滚动时阻止页面呈现。

虽然上面这段只提到touchstarttouchmove事件,但我发现它也适用wheel于 Chrome 和 Firefox 中的事件。

因此,如果您想制作作品,则必须将选项preventDefault()专门设置为.passivefalse


推荐阅读