跨浏览器需求:禁用触控板双指缩放但保留双指滚动功能
阻止触控板双指缩放但保留滚动的可行方案
问题背景
你使用的viewport meta标签仅对移动端浏览器生效,MacOS桌面端的Safari/Chrome并不遵守该规则,因此需要额外针对桌面端手势事件做处理。
可行方案
1. 精准区分滚动与缩放的Wheel事件
触控板双指缩放触发的wheel事件,会同时满足按住Ctrl键且deltaX和deltaY的绝对值相等、方向一致(缩放时双指同步移动,而滚动是单方向或非同步的斜向移动)。基于这个特征可以精准拦截缩放:
const ignorePinchToZoomEvent = (event: WheelEvent) => { // 仅拦截双指缩放触发的wheel事件 if (event.ctrlKey && Math.abs(event.deltaX) === Math.abs(event.deltaY)) { event.preventDefault(); } }; document.addEventListener("wheel", ignorePinchToZoomEvent, { passive: false });
注意:必须设置
passive: false,否则浏览器默认的被动事件模式会阻止preventDefault()生效。
2. 针对Safari的手势事件拦截
Safari支持专门的gesture系列事件(gesturestart/gesturechange),可以直接拦截缩放手势,完全不影响滚动功能:
const preventPinchGesture = (event: GestureEvent) => { // 当缩放比例不等于初始值时,阻止手势 if (event.scale !== 1) { event.preventDefault(); } }; document.addEventListener("gesturestart", preventPinchGesture, { passive: false }); document.addEventListener("gesturechange", preventPinchGesture, { passive: false });
3. 跨浏览器兼容方案
结合上述两种方法,同时处理wheel事件(覆盖Chrome等非Safari浏览器)和gesture事件(覆盖Safari),实现全兼容:
// 处理Chrome等浏览器的wheel事件 const handleWheelEvent = (event: WheelEvent) => { if (event.ctrlKey && Math.abs(event.deltaX) === Math.abs(event.deltaY)) { event.preventDefault(); } }; // 处理Safari的手势事件 const handleGestureEvent = (event: GestureEvent) => { if (event.scale !== 1) { event.preventDefault(); } }; document.addEventListener("wheel", handleWheelEvent, { passive: false }); document.addEventListener("gesturestart", handleGestureEvent, { passive: false }); document.addEventListener("gesturechange", handleGestureEvent, { passive: false });
注意事项
- 部分浏览器可能对触控板事件的参数有细微差异,建议在目标浏览器中测试调整判断条件(比如允许deltaX和deltaY有少量误差,用
Math.abs(event.deltaX - event.deltaY) < 10代替严格相等)。 - 不要全局阻止所有带
ctrlKey的wheel事件,否则会影响用户按住Ctrl键配合鼠标滚轮的正常操作(如果有)。
内容的提问来源于stack exchange,提问作者Nick Hingston
相关产品推荐
相关产品推荐

