javascript - 如何在桌面浏览器中从触控板上捕获捏缩放手势(并防止默认)?
问题描述
如果您在带有触控板的笔记本电脑上的 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">
但它没有帮助。
那么谷歌地图是如何做到的呢?当您在触控板上捏缩放时,它们如何防止默认行为(缩放整个页面)?
解决方案
我手头没有触控板,但既然你说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。这可以防止调用事件侦听器,因此它不能在用户滚动时阻止页面呈现。
虽然上面这段只提到touchstart
和touchmove
事件,但我发现它也适用wheel
于 Chrome 和 Firefox 中的事件。
因此,如果您想制作作品,则必须将选项preventDefault()
专门设置为.passive
false
推荐阅读
- javascript - 使用 && 运算符检查两个值 - ReactNative
- c++ - 两个线程可以共享 boost::asio tcp 套接字以进行独占读写吗?
- julia - Julia:无法将 Array{Number,1} 类型的对象“转换”为 GLM.LmResp 类型的对象
- sql - SQL查找具有唯一ID的行之间的差异
- safari - Applescript 和 Automator - Safari 卡住了,我必须按 Esc 才能继续
- javascript - 如果没有找到匹配项,为什么 indexOf 返回 -1?
- javascript - jquery 裁剪框更改选项
- dialogflow-es - 用户需要从 100 个项目列表中选择一个选项。在对话流中实现这一点的最佳方法是什么?
- java - 没有空格的字符串
- mysql - 带光标的事件不起作用