移动端滑动事件如何准确获取连续滑动的总距离?

Mc.彬丽 阅读 15

我在开发移动端卡片滑动删除功能时遇到了问题,用touchstart和touchmove计算滑动距离,发现每次滑动结束后的总距离不准确,特别是快速连续滑动时数值会突然跳变。

尝试在touchstart记录初始坐标,touchmove里计算差值累加,但发现当手指快速抬起再继续滑动时,之前的结束位置没有正确衔接,导致计算出错。比如先滑动了30px结束,再继续滑动20px,总距离却显示50px而不是预期的50?

这是我的代码示例:

<div @touchstart="start" @touchmove="move" @touchend="end">
  方法:记录startX,每次move计算deltaX累加到totalX
  问题:连续滑动时totalX会叠加上次的结束值
</div>

有没有更好的方式追踪手指从触屏到抬起整个过程的总位移?或者需要重置某些状态?目前用endX保存上次结束位置,但没起作用。

我来解答 赞 12 收藏
二维码
手机扫码查看
2 条解答
 ___嘉木
要解决这个问题,咱们得从事件的生命周期和状态管理入手。你的问题核心是连续滑动时总距离计算不准确,主要是因为没有正确处理手指抬起再触屏的状态衔接。我来一步步给你讲清楚怎么改。

第一步,明确几个关键点。移动端的滑动事件主要有三个:touchstarttouchmovetouchendtouchstart 是手指触屏时触发,touchmove 是手指移动时触发,touchend 是手指离开屏幕时触发。问题出在快速连续滑动时,第二次滑动的起点没有正确衔接上一次滑动的终点。

第二步,我们要引入一个变量来记录滑动是否中断了。具体来说,当手指抬起(touchend)后,下一次触屏(touchstart)应该重置一些状态,而不是直接累加到之前的总距离上。

第三步,代码实现上需要调整逻辑。我们用一个标志位来判断是否是新的滑动开始,同时保存每次滑动的起始点和结束点。下面是改进后的代码:


let startX = 0; // 当前滑动的起始点
let totalX = 0; // 总滑动距离
let lastEndX = 0; // 上一次滑动的结束点
let isSliding = false; // 是否正在滑动

function start(event) {
// 如果之前有滑动,标记为新滑动开始
if (!isSliding) {
startX = event.touches[0].pageX; // 记录当前触屏点
isSliding = true;
} else {
// 连续滑动时,重新记录起点
startX = event.touches[0].pageX;
}
}

function move(event) {
if (!isSliding) return; // 防止异常情况
let currentX = event.touches[0].pageX; // 获取当前手指位置
let deltaX = currentX - startX; // 计算本次滑动的增量
totalX = lastEndX + deltaX; // 更新总距离
console.log('当前总距离:', totalX);
}

function end() {
isSliding = false; // 标记滑动结束
lastEndX = totalX; // 保存上一次滑动的结束点
}


第四步,解释一下为什么这样写能解决问题。我们在 touchstart 中判断是否是新的滑动开始。如果是新的滑动,就重新记录起点;如果不是,继续使用上次的结束点作为参考。这样可以避免连续滑动时数值跳变的问题。lastEndX 的作用就是保存上一次滑动的最终位置,确保下次滑动时能正确衔接。

第五步,注意一些细节。比如 isSliding 的作用是用来防止在非滑动状态下误触发计算。另外,console.log 只是用来调试的,实际项目中可以去掉或者换成其他日志方式。

最后提醒一点,如果你的项目里有复杂的滑动逻辑,比如多指操作或者需要防抖处理,可能还需要进一步优化。不过按照这个思路,基本的连续滑动距离计算问题已经解决了。

希望这些对你有帮助!如果有不清楚的地方可以继续问。
点赞
2026-02-17 15:05
Air-利云
你这个问题挺常见的,主要是因为在连续滑动时,touchend和下一次touchstart之间的衔接没处理好。手指快速抬起再落下时,如果初始位置没有正确更新,就会导致总距离计算出错。

解决方法其实很简单,关键是要在touchend时保存最后一次的触摸位置,然后在下一次touchstart时用这个位置作为新的起点,而不是每次都从零开始算。

下面是修正后的代码逻辑:

let startX = 0;
let totalX = 0;
let lastX = 0; // 新增:记录上次结束时的位置

function start(event) {
startX = event.touches[0].clientX - lastX; // 起点基于上次结束位置
}

function move(event) {
const currentX = event.touches[0].clientX;
const deltaX = currentX - startX;
totalX += deltaX; // 累加差值
startX = currentX; // 更新起点
console.log('当前总距离:', totalX);
}

function end(event) {
lastX = event.changedTouches[0].clientX; // 记录手指离开时的位置
console.log('滑动结束,保存最后位置:', lastX);
}


重点说下改动:
1. 增加了lastX来保存每次滑动结束时的手指位置。
2. 在touchstart时,用lastX调整起点,确保连续滑动时起点是正确的。
3. touchend时一定要更新lastX,这样下次滑动才有参考。

调试看看,应该就能解决你提到的距离跳变问题了。如果还有其他异常情况,可能是手势识别的地方需要进一步优化。
点赞 8
2026-01-30 10:10