移动端Safari中touchEvents为何出现负时间戳?
解决iOS Safari上长按检测的时间戳异常问题
我之前也踩过一模一样的坑!你提到的iPhone 7+上出现的异常,大概率是iOS Safari对Event.timeStamp的实现和桌面端浏览器不一致导致的——虽然MDN文档明确说明两类时间戳都是从文档生命周期开始的毫秒数,但iOS Safari有时候会偷偷把Event.timeStamp的基准换成系统启动时间,而requestAnimationFrame的时间戳确实严格遵循文档生命周期的基准,这就导致两者对比时出现差值异常(比如负数、超大值)。
给你两个靠谱的解决方案:
1. 用performance.now()统一时间基准
这是最推荐的方案,performance.now()在所有现代浏览器(包括iOS Safari)里的定义都是从文档导航开始的高精度时间戳,和requestAnimationFrame的时间戳基准完全一致,不会出现基准错位的问题。
示例代码:
let pressStartTime = null; // 监听按下/触摸开始事件 const startPress = () => { pressStartTime = performance.now(); requestAnimationFrame(checkLongPress); }; // 监听松开/触摸结束事件 const endPress = () => { pressStartTime = null; }; // 检测长按逻辑 function checkLongPress() { if (!pressStartTime) return; const elapsedTime = performance.now() - pressStartTime; // 假设长按阈值是500毫秒 if (elapsedTime >= 500) { console.log('长按触发!'); endPress(); // 重置避免重复触发 return; } requestAnimationFrame(checkLongPress); } // 绑定事件(兼顾鼠标和触摸场景) const targetElement = document.getElementById('your-target'); targetElement.addEventListener('mousedown', startPress); targetElement.addEventListener('touchstart', startPress); targetElement.addEventListener('mouseup', endPress); targetElement.addEventListener('touchend', endPress); targetElement.addEventListener('mouseleave', endPress); // 防止鼠标移出后仍触发
2. 降级兼容旧版iOS(可选)
如果需要兼容更老的iOS版本(比如iOS 10及以前),可以做个简单的兼容性判断:如果发现Event.timeStamp和requestAnimationFrame时间戳的差值异常(比如负数),就切换到Date.now()来记录时间——虽然精度稍差,但基准是统一的。
比如在事件触发时:
const getCurrentTime = () => { // 优先用performance.now(),降级用Date.now() return typeof performance !== 'undefined' ? performance.now() : Date.now(); };
我之前用这个方案解决了iOS上长按检测的异常问题,你可以试试替换掉原来的Event.timeStamp,应该就能正常工作了!
内容的提问来源于stack exchange,提问作者Kristonitas
相关产品推荐
相关产品推荐

