移动端左右滑动和上下滑动手势冲突怎么处理?
在移动端页面里,同时存在左右滑动切换卡片和上下滑动页面的需求,但左右滑动总是被页面滚动劫持了。我用hammer.js监听了panstart事件,尝试通过event.direction判断方向再调用event.preventDefault(),但有时候左右滑动还是会触发页面滚动…
const hammer = new Hammer(element);
hammer.get('pan').set({ direction: Hammer.DIRECTION_ALL });
hammer.on('panstart', (e) => {
if (e.direction === Hammer.DIRECTION_HORIZONTAL) {
e.target.style.touchAction = 'none'; // 这样设置有效吗?
e.preventDefault();
}
});
试过给元素加touch-action: pan-y;,但有些安卓机还是不行。有没有更稳定的解决方法?
touch-action: pan-y;确实是一个正确的方向,但它在某些安卓设备上的兼容性确实不够好。我们可以通过更精细的事件控制来解决。首先,问题的核心是
panstart事件触发时,手势的方向可能还没有完全确定,导致e.direction判断不准确。另外,e.preventDefault()在某些情况下并不能完全阻止默认滚动行为。一个更稳定的解决方案是结合
touch-action和手势事件的动态判断。具体来说,可以这样处理:1. 给目标元素设置
touch-action: none;,这会禁用所有默认的触摸行为。2. 在
panstart中判断初始滑动方向,如果检测到是水平滑动,就保持禁止滚动;如果是垂直滑动,则允许页面滚动。下面是改进后的代码示例:
几点说明:
- 这里通过
e.angle来判断滑动方向,比直接用e.direction更精确。- 动态设置
touch-action可以有效避免手势冲突。- 在
panend中重置样式和状态,确保下一次滑动正常。如果你发现某些安卓机型依然有问题,建议再调试看看是否需要对特定设备做兼容性处理,比如强制监听
touchstart和touchmove原生事件,并手动调用preventDefault()。最后提醒一下,测试的时候多用真机,模拟器有时候表现不太一样。