我正在尝试做类似于嵌入式 Google 地图的事情。我的组件应该忽略单指触摸(允许用户滚动页面)和在组件之外的捏合手势(允许用户缩放页面),但应该对双指触摸作出反应(允许用户在组件内导航),并在这种情况下禁止任何默认操作。
我如何阻止触摸事件的默认处理,但只在用户用两个手指与我的组件交互时?
我尝试过:
我尝试捕获
onTouchStart
、onTouchMove
和onTouchEnd
。结果发现,在 Firefox Android 上,当在组件上进行捏合手势时,第一个触发的事件是带有单指触摸的onTouchStart
,然后是带有两个触摸的onTouchStart
,然后是onTouchMove
。但在onTouchMove
处理程序中调用event.preventDefault()
或event.stopPropagation()
并不能(总是)停止页面缩放/滚动。在第一次调用onTouchStart
时阻止事件升级确实有帮助——不幸的是,那时我还不知道是否会是多点触控,所以我不能使用这个方法。第二种方法是在
document.body
上设置touch-action: none
。这在 Chrome Android 上可以工作,但我只能在 Firefox Android 上将其设置在所有元素上(除了我的组件)。因此,虽然这是可行的,但它似乎可能会产生不需要的副作用和性能问题。编辑:进一步测试发现,如果在触摸开始前设置 CSS,则此方法仅适用于 Chrome。换句话说,如果我在检测到 2 根手指时注入 CSS 样式,则touch-action
将被忽略。因此,这在 Chrome 上没有用处。我还尝试在组件挂载时添加一个新的事件监听器:
document.body.addEventListener("touchmove", ev => { ev.preventDefault(); ev.stopImmediatePropagation(); }, true);
(对于
touchstart
同样适用)。在Firefox Android中这样做可以工作,但在Chrome Android上则没有任何效果。
我已经想不出更好的办法了。是否有一种可靠的跨浏览器方法来实现Google显然所做的事情,或者他们使用了多个技巧并在每个浏览器上进行了大量测试才使其正常工作?如果有人指出我的方法存在错误或提出新的方法,我将不胜感激。
touchmove
事件并向组件添加了 CSS。这两个是否都是必需的,或者我们可以不用在组件上使用 CSS? - T.Woodytouch-action
选项性能更佳(且更好),但只有在您事先设置它(在touchstart
事件之前)时才能使用。在我的情况下,这不是一个选择,因为我需要根据手指数量实现不同的行为,所以我必须等待touchstart
事件。 - johndodopointerdown
,pointermove
),则preventDefault
和stopImmediatePropagation
对默认触摸操作没有任何影响。必须使用touchstart
和touchmove
显式地防止默认操作。 - The Conspiracy