Vue手势滑动方向检测不准怎么办?

慕容俊荣 阅读 32

在移动端用Vue做卡片滑动切换时,检测滑动方向总是出错。比如向右滑应该删除卡片,但经常反向触发。我试过记录touchstart和touchend的坐标差,但计算出来的方向不准。

代码是这样写的:


<template>
  <div 
    @touchstart="handleTouchStart" 
    @touchend="handleTouchEnd"
  >可滑动区域</div>
</template>

<script>
export default {
  methods: {
    handleTouchStart(e) {
      this.startX = e.touches[0].clientX;
      this.startY = e.touches[0].clientY;
    },
    handleTouchEnd(e) {
      const endX = e.changedTouches[0].clientX;
      const endY = e.changedTouches[0].clientY;
      if(endX - this.startX > 20) {
        console.log('向右滑');
      } else if(this.startX - endX > 20) {
        console.log('向左滑');
      }
    }
  }
}
</script>

问题出现在快速滑动时方向判断会反转,有时候横向滑动还会触发纵向逻辑。明明设置了20像素的阈值,但实际滑动距离明显超过却没反应...

我来解答 赞 7 收藏
二维码
手机扫码查看
2 条解答
Des.怡博
你这个方向判断没考虑滑动的连续性和角度,光靠起点终点差值容易误判。应该加个最小位移阈值和滑动角度过滤,只认明显的横向滑动。

handleTouchEnd(e) {
const endX = e.changedTouches[0].clientX;
const endY = e.changedTouches[0].clientY;
const diffX = endX - this.startX;
const diffY = endY - this.startY;

// 最小滑动距离
if (Math.abs(diffX) < 30) return;
// 防止斜向误触
if (Math.abs(diffY) > Math.abs(diffX)) return;

if (diffX > 0) {
console.log('向右滑');
} else {
console.log('向左滑');
}
}
点赞 3
2026-02-12 21:03
A. 顺红
A. 顺红 Lv1
你这个问题我见过不少前端同事踩坑,主要是因为单纯用坐标差来判断方向确实不靠谱。快速滑动时手指可能会带出一些奇怪的轨迹,导致判断失误。

建议你在 touchmove 事件里做方向检测,而不是等到 touchend 才算。这样可以实时跟踪滑动趋势,避免误判。另外加个斜率计算,防止斜着滑触发错误方向。

下面是改过的代码:

export default {
data() {
return {
startX: 0,
startY: 0,
isHorizontal: null // 用来标记是否是横向滑动
};
},
methods: {
handleTouchStart(e) {
this.startX = e.touches[0].clientX;
this.startY = e.touches[0].clientY;
this.isHorizontal = null; // 每次开始都重置方向
},
handleTouchMove(e) {
const moveX = e.touches[0].clientX;
const moveY = e.touches[0].clientY;

if (this.isHorizontal === null) {
// 刚开始滑动时判断主要方向
const deltaX = Math.abs(moveX - this.startX);
const deltaY = Math.abs(moveY - this.startY);

if (deltaX > deltaY && deltaX > 10) {
this.isHorizontal = true; // 主要横向滑动
} else if (deltaY >= deltaX && deltaY > 10) {
this.isHorizontal = false; // 主要纵向滑动
}
}
},
handleTouchEnd(e) {
if (this.isHorizontal === null) return; // 没滑够距离直接忽略

const endX = e.changedTouches[0].clientX;
const endY = e.changedTouches[0].clientY;

if (this.isHorizontal) {
if (endX - this.startX > 20) {
console.log('向右滑');
} else if (this.startX - endX > 20) {
console.log('向左滑');
}
} else {
// 如果是纵向滑动,这里可以处理上下逻辑
}
}
}
}


重点是加了个 isHorizontal 标记,在 touchmove 时就确定主要滑动方向。这样即使用户手抖带出点斜线,也不会影响最终判断。阈值还是保持20像素,但增加了方向判定的准确性。

最后吐槽一句,前端的手势识别有时候真让人头大,不过这种处理方式在我们项目里已经挺稳定了。
点赞 9
2026-01-30 16:15