使用方法
- 先选「挑战模式」:默认是 10 秒计时挑战,也可以切成 100 次计数挑战。「单局时长」默认 10 秒,允许 1~60 的整数;「目标击数」默认 100 次,允许 10~500 的整数。
- 把指针移到灰色大方块上,按下的第一瞬间就开始计时并计为第 1 击,不需要先找「开始」按钮。
- 计时模式里一直点,右上角数字从 10 倒数到 0 自动结束;计数模式里点到第 100 下自动结束,用时由工具记录。
- 结束后结果区给出五项指标:击数、用时、CPS、1 秒窗口峰值、平均每击占用;在大方块上再点一下就清空成绩、准备下一局。
- 改完参数想重新来,在输入框里按 Enter 或点「重置本局」;点「复制成绩」把五项指标一次性复制出去。
这个点击速度测试每秒点击能解决什么问题
一是把「手速」变成一个可比较的数字。换鼠标、换触控板、换触屏之前各测一局,10 秒模式下的击数变化就是最直接的体感差距,比「感觉快了点」可靠。
二是排查外设故障。鼠标微动老化会出现「点一下触发两下」或「连点丢帧」,典型表现是同一只手的 CPS 突然比平时低一两档,而换一只鼠标立刻恢复。按键抖动与回报率问题在纯文本编辑里看不出来,在 CPS 测试里很显眼。
三是训练前建立基线。节奏类游戏、绘画双击、电竞换弹这些场景对连续点击频率有实际要求,先量出安静状态下的稳定 CPS,训练后再测一次,比较的是同一个口径下的数字,而不是两次不同的心情。
四是区分「快」和「稳」。整局 CPS 是平均值,1 秒窗口峰值是瞬时爆发力,两者差距多大说明节奏是否均匀:峰值比平均高出一半以上,通常意味着开局几击很猛、后面明显掉速。
本页不做这些事:不记录历史成绩、不做排行榜、不给鼠标打分、不模拟自动点击。想数清某段时间里点了多少下(而不是多快),用页面底部的「点击计数器」;想测鼠标本身的工作状态,用「鼠标测试」。
计数与计时原理:pointerdown、单调时钟与 1 秒滑动窗口
计数用的是 pointerdown,而不是 click。这是这个点击速度测试每秒点击最关键的一处设计。按 W3C Pointer Events Level 2 的定义,pointerdown 在指针按下的那一帧就派发,一根手指、一支笔和一只鼠标走的是同一条事件通道(靠 pointerType 区分 mouse/touch/pen)。而 click 是「按下 + 抬起」在同一个元素上配对成功后合成的事件:连续快速点击时,如果指针在按下与抬起之间滑出了元素边界,或者浏览器把同一帧内的多次操作合并,click 就会被丢弃,测出来的成绩会偏低。用 pointerdown 计数可以绕开合成环节,按下多少下就是多少下。
计时用的是 performance.now()。它按 W3C High Resolution Time Level 2 规范返回一个单调递增的毫秒浮点数(DOMHighResTimeStamp),只往前走、不会倒退。常见的 Date.now() 读的是墙上时钟,遇到 NTP 校时或用户手动改时间会跳变,两击之间算出的间隔甚至可能是负数。performance.now() 不吃这一套,而且带小数,配合 Math.ceil 给倒计时显示取整。
刷新循环用 requestAnimationFrame,不用 setInterval 累加。如果每 100 毫秒把计数器加 0.1 秒,页面被切到后台时浏览器会把定时器节流到至少 1000 毫秒一次,10 秒的赛程会被拉长到十几秒。本工具每一帧只做一件事:读一次 performance.now(),和「开始时刻 + 时长」比一下,超了就结束。计时长度由时间戳相减得出,和帧率无关,机器卡顿也不会把 10 秒算成 12 秒。
峰值成绩是 1 秒滑动窗口的最大值。维护一个双指针区间:右指针每次新加一击,左指针在「区间跨度 ≥ 1000 毫秒」时右移,区间内元素个数的最大值就是峰值。算法是均摊 O(N),68 击只需要 68 次比较。
几个参数的取值理由。时长默认 10 秒:1 秒太短,多打或少打一击就带来 1 CPS 的抖动,同一只手连测三次能差出 2 CPS;60 秒又太长,前臂会进入耐力衰减区,量到的其实是肌耐力而不是爆发力,10 秒正好落在「足够平均、又不至于疲劳」的区间。目标击数默认 100:在 6~8 CPS 的常见区间里换算成 12~17 秒,击数是整数、评分不受时间分辨率影响。结果显示保留 1 位小数:10 秒模式下每多一击恰好是 0.1 CPS,1 位小数刚好和「一击」的粒度同量级,再多一位显示的就是噪声了。
完整示例(数值仅作演示)
示例条件与页面打开时的默认值完全一致:10 秒计时挑战、单局时长 10 秒。假设这一局共记录到 68 击,计时窗口固定为 10.000 秒,那么:
- 整局 CPS = 68 ÷ 10.000 = 6.800,保留 1 位小数显示 6.8;
- 平均每击占用 = 10000 ÷ 68 = 147.06 毫秒,显示 147 ms;
- 这一局的 1 秒滑动窗口内最多装下 11 击,即峰值 11 击/秒,比整局平均的 6.8 高出 62%;
- 按 6.8 这个水平换算,切到 100 次计数挑战大约需要 14.71 秒。
同一只手切到100 次计数挑战再测一局:从第 1 击到第 100 击实际跨度为 14.74 秒,则 CPS = 100 ÷ 14.74 = 6.784,保留 1 位小数仍是 6.8,平均每击占用 147.40 毫秒。两种模式给出的 CPS 落在同一档,说明口径是一致的;如果两种模式差出 0.5 CPS 以上,通常是第一局还没进入节奏。
下面这段就是页面打开时结果区显示的示例文本,你实测得到的会是自己的数字:
击数 68 击|用时 10.00 秒|CPS 6.8|峰值(1 秒窗口)11 击|平均每击 147 ms 判定:优秀;整局峰值高于平均 62%,属于「开局爆发、后段略降」的节奏。
CPS 档位与等效成绩对照表
下面把 1~20 CPS 逐档折算成「每 10 秒能点多少下」和「点满 100 次要多久」,并给出档位判定。整张表由页面里的复算脚本按 10 × CPS 与 100 ÷ CPS 算出,方便你把手上的原始击数直接对号入座。
| CPS | 每 10 秒击数 | 点满 100 次耗时 | 档位 |
|---|---|---|---|
| 1 | 10 击 | 100.00 秒 | 起步 |
| 2 | 20 击 | 50.00 秒 | 起步 |
| 3 | 30 击 | 33.33 秒 | 起步 |
| 4 | 40 击 | 25.00 秒 | 偏慢 |
| 5 | 50 击 | 20.00 秒 | 平均 |
| 6 | 60 击 | 16.67 秒 | 良好 |
| 7 | 70 击 | 14.29 秒 | 优秀 |
| 8 | 80 击 | 12.50 秒 | 很强 |
| 9 | 90 击 | 11.11 秒 | 很强 |
| 10 | 100 击 | 10.00 秒 | 顶尖 |
| 11 | 110 击 | 9.09 秒 | 顶尖 |
| 12 | 120 击 | 8.33 秒 | 顶尖 |
| 13 | 130 击 | 7.69 秒 | 顶尖 |
| 14 | 140 击 | 7.14 秒 | 顶尖 |
| 15 | 150 击 | 6.67 秒 | 顶尖 |
| 16 | 160 击 | 6.25 秒 | 顶尖 |
| 17 | 170 击 | 5.88 秒 | 顶尖 |
| 18 | 180 击 | 5.56 秒 | 顶尖 |
| 19 | 190 击 | 5.26 秒 | 顶尖 |
| 20 | 200 击 | 5.00 秒 | 顶尖 |
「档位」只是本工具给出的粗分类,边界定在 3/4/5/6/7/9 CPS:单指连点的常见区间是 6~8 CPS,两指或双键交替可以稳定到 12~16 CPS,14 CPS 以上在普通办公鼠标上已经很难靠单指达到。触控屏多指同时按下时,pointerdown 会为每根手指各派发一次事件,成绩自然更高——这既不是 bug,也不是作弊,但和单指的数值不在同一个口径上,横向比较时要说清楚用的是几根手指。
输入范围、边界与舍入
- 单局时长 1~60 的整数秒。小数会被拒绝:0.5 秒的窗口里手速再快也只有几击,除以 0.5 会把时间分辨率的问题放大成很大的 CPS 误差。上限 60 秒是考虑到再长就变成耐力测试了。
- 目标击数 10~500 的整数。下限 10 是为了让样本够用;上限 500 对应 1 CPS 的极端慢速也不过 500 秒,页面不会长时间占着计时循环。
- 击数至少是 1。第一击既开始计时也计为一次点击,所以「用时为正、击数为零」的除法情形不会出现;代码里仍留了一条
n === 0的兜底分支,返回 0.0 而不是让NaN或Infinity跑到界面上。 - CPS 保留 1 位小数,采用四舍五入。舍入后的可分辨区间宽 0.1 CPS:6.75~6.849 都显示 6.8,在 10 秒模式里这正好等于一击之差。想看出更细的差别,把单局时长拉到 60 秒,1 击的分辨率就降到约 0.017 CPS。
- 计时模式的用时是设定值,不是实测值。选 10 秒就是 10.000 秒,CPS 用「击数 ÷ 10」算,好处是同一只手的多次结果可以直接比。计数模式刚好相反,用时实测、击数固定,两种口径不要混着比较。
- 键盘不参与计分。Enter 只触发重置与参数校验,空格也只在大方块获得焦点时做同样的动作。这是刻意的:按住回车键会产生「按键重复」事件流,一秒能灌进来几十次,放行的话测出来的就不是手速了。触屏上的多点触控则会逐指计入,属于真实输入。
- 脚本合成的事件不拦截,但也不可信。用
element.dispatchEvent()造出来的pointerdown会把成绩刷到几百 CPS,这类事件的isTrusted属性是false。本工具不做拦截(拦截也无法阻止外部工具在更外层模拟),只在正文里说明:凡是没有注明测试条件的高分截图,都要先问一句是不是自动点击。 - 时间分辨率不是瓶颈。规范要求
performance.now()至少细化到 5 微秒,主流浏览器按自身策略把它钳到 100 微秒到 1 毫秒之间。即便按最粗的 1 毫秒算,10 秒赛程的相对误差也只有 0.01%,比手指抖动小了三个数量级。
常见问题
为什么用 pointerdown 而不用 click 计数?
click 是按下与抬起配对成功后才由浏览器合成的事件,快速连点时如果指针在两次动作之间滑出了元素边界,或者同帧内的操作被合并,事件就会被丢掉,成绩偏低。这个点击速度测试每秒点击改用 pointerdown,它在按下那一瞬间就派发,不依赖抬起动作,也就不会因为手抖滑出边界而漏计。
两根手指同时点,或者左右键交替按,算不算数?
算。触屏上 pointerdown 会为每根按下的手指各派发一次事件,鼠标左右键也会各自触发一次。所以双指、双键交替的成绩通常会比单指高一截,这也是很多「世界纪录」视频里用的手法。关键是横向比较时注明用了几根手指、哪种指法,不同指法的数值不在同一口径上。
页面切到后台,计时会不会变慢?
不会。本工具用 performance.now() 读单调时钟,每帧只做一次时间戳比较,长度由「开始时刻 + 时长」决定,和刷新次数无关。切到后台时浏览器会暂停 requestAnimationFrame,切回来的第一帧就会读到真实经过的时间并立刻按结果结束——成绩会偏低(因为你没法在后台点击),但不会被算成超过 10 秒。
10 秒模式和 100 次模式,哪个更准?
两者都准,只是口径不同。10 秒模式固定分母、击数浮动,用时永远是 10.000 秒;100 次模式固定分子、用时实测。前者适合看「这段时间里能点多少下」,后者适合看「点完固定数量要多久」。要注意的是 100 次模式的用时是「第 1 击到第 100 击」的跨度,点数比 10 秒模式少了固定的 10 秒约束,两次测试的起始节奏差别会被放大。
为什么峰值比平均 CPS 高出这么多?
因为平均把整局的起手、换节奏和收尾都摊平了。本工具用 1 秒滑动窗口取整局最大值:窗口宽度固定 1000 毫秒,向右逐击推进,记下窗口内最多装下几击。开局两三击往往最快,之后每击的间隔会慢慢变长,所以峰值通常比平均值高出 30%~60%;示例这一局平均值 6.8、峰值 11,高出 62%,属于典型的「发起快、越点越慢」。
鼠标回报率会不会卡住我的上限?
基本不会,但可以算一算。回报率是鼠标每秒向系统上报位置的次数,125 Hz 对应相邻上报最小间隔 8 毫秒,1000 Hz 对应 1 毫秒。也就是说 125 Hz 的鼠标理论上每秒能上报 125 次,远高于人手 16 CPS 左右的上限,够用。真正会拖后腿的是回报率异常(例如劣质无线接收器掉到几十赫兹)或微动抖动,表现是同一只手忽然掉一档。
按回车或者空格能刷分吗?
不能。输入框里按 Enter 只会做一次参数校验并重置本局,空格只有在大方块拿到焦点、且按下时长按不会产生按键重复时才触发同样的动作,两者都不计入击数。这样设计是因为按住键盘会产生每几十毫秒一次的重复事件,放行的话一秒能灌进几十次,测出来的不是手速而是系统的按键重复率。
成绩会被记录或上传吗?
不会。整局的时间戳只存在当前页面的内存里,算完即用即弃,刷新页面就没了,也没有任何网络请求。想自己确认,打开开发者工具的 Network 面板点一局,可以看到没有任何新请求发出。要留档就点「复制成绩」,五项指标会以纯文本进剪贴板。