移动端手势冲突时如何处理优先级?

博主爱巧 阅读 3

我在做移动端页面,同一个区域既要支持左右滑动切换,又要支持上下滑动滚动,结果两个手势老打架,到底该怎么控制谁先响应啊?

试过用 touchstart 里 preventDefault() 拦截,但一拦就全没了,体验特别差。也看过一些库比如 Hammer.js,但项目里不想加太多依赖……有没有更轻量的方案?

下面是我现在的结构,外层是横向滑动容器,里面内容要能纵向滚动:

<div class="swipe-container" touch-action="none">
  <div class="slide active">
    <div class="scroll-content">
      <p>很多内容...</p>
      <p>需要能上下滑动查看</p>
    </div>
  </div>
</div>
我来解答 赞 1 收藏
二维码
手机扫码查看
1 条解答
a'ゞ正利
这问题我踩过坑,核心思路就是判断滑动方向,然后动态决定锁死哪个。不要在 touchstart 里无脑 preventDefault,要在 touchmove 里根据实际滑动角度来决定。

直接贴代码:

let startX = 0, startY = 0, locked = false;

document.querySelector('.swipe-container').addEventListener('touchstart', e => {
startX = e.touches[0].clientX;
startY = e.touches[0].clientY;
locked = false;
}, { passive: true });

document.querySelector('.swipe-container').addEventListener('touchmove', e => {
if (locked) return;

const dx = Math.abs(e.touches[0].clientX - startX);
const dy = Math.abs(e.touches[0].clientY - startY);

// 横向滑动角度大于45度,锁定横向,阻止纵向滚动
if (dx > dy && dx > 10) {
locked = true;
// 这里执行你的横向切换逻辑
}
// 纵向滑动为主,不阻止,让内部滚动
}, { passive: true });


关键点就是 passive: true 别设成 false,不然滚动性能会卡成狗。横向滑动时你手动处理切换动画就行,纵向直接放行让浏览器原生滚动接管。另外那个 touch-action="none" 可以删掉了,这属性太暴力,会把所有手势都干掉。
点赞
2026-03-02 10:14