You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现准确实时获取文档上的活跃触摸点数量?

问题:如何实现即时且准确获取屏幕触摸点数量的函数

我希望实现一个能即时且准确获取屏幕触摸点数量的函数,尝试了两段代码但均存在问题:

第一段带防抖的代码

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 16:47:19