DoubleTap 手势在移动端怎么监听才有效?

Prog.朝炜 阅读 11

我在用原生 JS 做一个移动端图片预览功能,想实现双击放大,但试了好几种方法都识别不到 doubletap。用 dblclick 事件在手机上根本没反应,是这个事件不支持移动端吗?

后来我试着自己用 touchstart 计时判断,但总误触发单击或者三连点,逻辑特别混乱。有没有靠谱的写法?比如下面这种尝试:

let lastTap = 0;
element.addEventListener('touchend', (e) => {
  const now = Date.now();
  if (now - lastTap <= 300) {
    console.log('double tap!');
  }
  lastTap = now;
});

这段代码有时候能触发,有时候又不行,尤其在快速滑动后点击就完全失效了,到底该怎么正确处理?

我来解答 赞 16 收藏
二维码
手机扫码查看
1 条解答
东宇~
东宇~ Lv1
啊,移动端的双击手势确实是个坑,我之前也被这个折磨过。首先你要明白,dblclick在移动端基本就是个摆设,因为它最初是为鼠标设计的,移动端touch事件的触发机制完全不一样。

我来给你一个经过实战检验的方案,这个方案要处理几个关键点:
1. 区分单击和双击
2. 防止快速滑动误触
3. 处理多点触控的情况

直接上代码吧,我加详细注释给你解释:

// 定义双击时间阈值(单位毫秒)
const DOUBLE_TAP_DELAY = 300;
let lastTapTime = 0;
let timer;
let isDoubleTap = false;

element.addEventListener('touchstart', function(e) {
// 排除多点触控的情况
if (e.touches.length > 1) return;

const currentTime = Date.now();

// 判断是否在阈值时间内再次点击
if (currentTime - lastTapTime < DOUBLE_TAP_DELAY) {
clearTimeout(timer);
isDoubleTap = true;
handleDoubleTap(e);
return;
}

// 重置状态
isDoubleTap = false;

// 设置一个延迟执行单击的定时器
timer = setTimeout(() => {
if (!isDoubleTap) {
handleSingleTap(e);
}
}, DOUBLE_TAP_DELAY);

lastTapTime = currentTime;
});

// 处理滑动时取消点击事件
element.addEventListener('touchmove', function(e) {
clearTimeout(timer);
});

function handleDoubleTap(e) {
console.log('成功触发双击!');
// 这里放你的双击逻辑
e.preventDefault(); // 阻止默认行为
}

function handleSingleTap(e) {
console.log('这是单击');
// 这里放你的单击逻辑
}


这个方案比你的尝试多了几个关键处理:
1. 加入了touchmove事件监听,滑动时会取消点击判定
2. 使用setTimeout来延迟执行单击事件,给双击判定留出时间窗口
3. 添加了isDoubleTap状态标识,防止双击后仍然触发单击
4. 排除了多点触控的情况

另外有个小技巧,实际项目中你可能会发现有时候双击后页面会短暂缩放,这是因为浏览器默认的双击缩放行为。解决方法是在meta标签里加上:

<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">


如果你觉得这个实现还是有点复杂,可以考虑用现成的库比如hammer.js,但了解原生实现原理总是有好处的。
点赞
2026-03-07 12:12