移动端手势滑动和点击冲突怎么解决?

长孙素香 阅读 4

我在做一个移动端的图片轮播组件,左右滑动切换图片,同时每张图片也能点击跳转。但经常出现滑动后还触发了点击事件,体验很奇怪。

试过在 touchstart 里记录位置,touchend 判断位移,如果超过阈值就阻止点击,但有时候还是会有误触。有没有更靠谱的处理方式?

现在判断逻辑大概是这样:

let startX, startY;
element.addEventListener('touchstart', e => {
  startX = e.touches[0].clientX;
  startY = e.touches[0].clientY;
});
element.addEventListener('touchend', e => {
  const endX = e.changedTouches[0].clientX;
  const endY = e.changedTouches[0].clientY;
  const dx = Math.abs(endX - startX);
  const dy = Math.abs(endY - startY);
  if (dx > 10 || dy > 10) {
    e.preventDefault(); // 想阻止点击
  }
});
我来解答 赞 5 收藏
二维码
手机扫码查看
1 条解答
尚斌 Dev
处理移动端手势滑动和点击冲突这个问题确实挺头疼的,不过你已经走对了路。你当前的思路是记录触摸开始和结束的位置,然后根据移动的距离来判断是滑动还是点击。这个方法是可以的,但有时候还是会有点误判,尤其是在用户滑动距离接近阈值的时候。

一个改进的方法是在 touchstart 时设置一个标志位,在 touchmove 中根据滑动距离修改这个标志位,然后在 touchend 中根据这个标志位来决定是否阻止默认的点击行为。这样可以更准确地区分滑动和点击。

试试下面的代码吧:

let startX, startY, isScrolling;

element.addEventListener('touchstart', e => {
startX = e.touches[0].clientX;
startY = e.touches[0].clientY;
isScrolling = false; // 初始状态为不是滑动
});

element.addEventListener('touchmove', e => {
const endX = e.touches[0].clientX;
const endY = e.touches[0].clientY;
const dx = Math.abs(endX - startX);
const dy = Math.abs(endY - startY);

if (dx > 10 || dy > 10) {
isScrolling = true; // 如果移动超过阈值,则认为是在滑动
}
});

element.addEventListener('touchend', e => {
if (isScrolling) {
e.preventDefault(); // 如果是在滑动,阻止点击事件
}
});


这样改之后,isScrolling 标志位会在用户滑动时被设置为 true,从而在 touchend 中阻止点击事件。希望这个方法能帮到你!
点赞
2026-03-23 14:00