如何实现准确实时获取文档上的活跃触摸点数量?
问题:如何实现即时且准确获取屏幕触摸点数量的函数
我希望实现一个能即时且准确获取屏幕触摸点数量的函数,尝试了两段代码但均存在问题:
第一段带防抖的代码
async number() { return new Promise((resolve, reject) => { let num = 0; let timeoutId = null; const updateNum = (e) => { num = e.touches.length; if (timeoutId) { clearTimeout(timeoutId); } timeoutId = setTimeout(() => { resolve(num); timeoutId = null; }, 50); }; document.addEventListener('touchstart', updateNum); document.addEventListener('touchend', updateNum); }); }
该代码在快速触摸屏幕时,有时会错误将num解析为1(实际应为0),添加防抖后仍未解决问题。
第二段无防抖的代码
async number() { return new Promise((resolve, reject) => { let num = 0; const updateNum = (e) => { num = e.touches.length; resolve(num); }; document.addEventListener('touchstart', updateNum); document.addEventListener('touchend', updateNum); document.addEventListener('touchmove', updateNum); }); }
但这段代码在同时添加两个触摸点时,解析出的数值不准确。我是新手,希望得到帮助。
解决方案
你的核心问题在于用Promise一次性返回结果,但触摸是持续的状态变化,Promise只能resolve一次,后续触摸事件的更新无法传递出去。正确思路是通过持续监听事件来同步触摸状态,而非只返回单次结果。
方案1:用回调实时响应触摸数变化
适合需要实时触发操作的场景:
function setupTouchCounter(callback) { let currentTouchCount = 0; const updateCount = (e) => { currentTouchCount = e.touches.length; callback(currentTouchCount); }; // 绑定所有触摸相关事件,包括系统打断触摸的touchcancel document.addEventListener('touchstart', updateCount); document.addEventListener('touchend', updateCount); document.addEventListener('touchmove', updateCount); document.addEventListener('touchcancel', updateCount); // 返回移除监听的函数,避免内存泄漏 return () => { document.removeEventListener('touchstart', updateCount); document.removeEventListener('touchend', updateCount); document.removeEventListener('touchmove', updateCount); document.removeEventListener('touchcancel', updateCount); }; } // 使用示例 const removeListener = setupTouchCounter(count => { console.log('当前触摸点数量:', count); // 这里可以直接处理业务逻辑,比如更新UI }); // 不需要监听时调用移除函数 // removeListener();
方案2:用类封装触摸状态
适合需要在多处随时获取当前触摸数的场景:
class TouchCounter { constructor() { this.currentCount = 0; this.updateCount = this.updateCount.bind(this); this.bindEvents(); } updateCount(e) { this.currentCount = e.touches.length; } bindEvents() { document.addEventListener('touchstart', this.updateCount); document.addEventListener('touchend', this.updateCount); document.addEventListener('touchmove', this.updateCount); document.addEventListener('touchcancel', this.updateCount); } unbindEvents() { document.removeEventListener('touchstart', this.updateCount); document.removeEventListener('touchend', this.updateCount); document.removeEventListener('touchmove', this.updateCount); document.removeEventListener('touchcancel', this.updateCount); } getCount() { return this.currentCount; } } // 使用示例 const counter = new TouchCounter(); // 随时获取当前触摸数 console.log(counter.getCount()); // 不需要时解绑事件 // counter.unbindEvents();
原代码问题说明
- 第一段代码:Promise仅能resolve一次,快速触摸时,touchend的结果可能被之前未完成的timeout覆盖,最终返回旧值。
- 第二段代码:同样Promise只resolve一次,同时按下两个触摸点时,第一个touchstart触发resolve后,后续事件的更新无法再传递出去,导致拿到的数值滞后。
内容的提问来源于stack exchange,提问作者Jax
相关产品推荐
相关产品推荐

