节流是解决鼠标移动事件高频触发导致卡顿的有效手段,通过限制单位时间执行次数兼顾轨迹连续性与性能;推荐用requestAnimationFrame实现帧率同步的高精度节流,兼容方案可用时间戳+状态标记手动控制间隔。

节流(Throttle)是解决鼠标移动事件高频触发导致绘制卡顿、性能下降的有效手段。核心思路是限制单位时间内最多执行一次绘制逻辑,既保留轨迹连续性,又避免无意义的重复计算和渲染。
为什么鼠标移动需要节流而不是防抖
鼠标轨迹追踪要求“尽可能还原移动路径”,不能丢弃中间关键点;而防抖会只响应最后一次移动,导致轨迹断开或严重滞后。节流则按固定间隔(如 16ms 或 30ms)采样,兼顾流畅性与性能。
用 requestAnimationFrame 实现高精度节流(推荐)
利用浏览器刷新机制(通常 60fps ≈ 16.6ms),确保绘制与屏幕刷新同步,视觉更平滑,且不阻塞主线程:
let lastX = 0, lastY = 0;
let isDrawing = false;
<p>function drawLine(x, y) {
// 例如:canvas.lineTo(x, y); canvas.stroke();
}</p><p>function handleMouseMove(e) {
const x = e.clientX;
const y = e.clientY;</p><p>if (!isDrawing) {
isDrawing = true;
requestAnimationFrame(() => {
drawLine(x, y);
isDrawing = false;
});
}
}</p><p>document.addEventListener('mousemove', handleMouseMove);
✅ 优势:自动对齐帧率、零手动计时器、无内存泄漏风险
⚠️ 注意:需配合 lastX/lastY 或累积点数组实现线段连接,否则只画离散点
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
立即学习“Java免费学习笔记(深入)”;
用时间戳 + 状态标记的手动节流(兼容旧环境)
适合需精确控制间隔(如固定 30ms)、或需记录完整采样点的场景:
let lastTime = 0;
const THROTTLE_DELAY = 30; // ms
const points = [];
<p>function throttleMouseMove(e) {
const now = Date.now();
if (now - lastTime < THROTTLE_DELAY) return;</p><p>lastTime = now;
points.push({ x: e.clientX, y: e.clientY });</p><p>// 批量绘制(例如每 5 个点连成一段)
if (points.length >= 5) {
renderPath(points);
points.length = 0; // 清空
}
}</p><p>function renderPath(pts) {
// canvas.beginPath();
// pts.forEach((p, i) => i === 0 ? canvas.moveTo(p.x, p.y) : canvas.lineTo(p.x, p.y));
// canvas.stroke();
}</p><p>document.addEventListener('mousemove', throttleMouseMove);
- 用
Date.now()比setTimeout更可靠,避免定时器堆积 - 建议缓存点数组再批量绘制,减少 canvas API 调用次数
- 可加距离阈值(如两点间距 > 2px 再记录),进一步精简冗余点
进阶优化:结合画布离屏渲染与坐标压缩
高频长轨迹下,直接在主 canvas 绘制仍可能掉帧。可:
- 用
OffscreenCanvas(现代浏览器)或内存 canvas 预绘制轨迹段 - 对点序列做 RDP 算法 压缩,保留形状特征,减少点数 60%+
- 启用 canvas 的
willReadFrequently: true(若需频繁读取像素)
实际项目中,requestAnimationFrame 节流 + 批量点绘制已覆盖 95% 场景,复杂压缩按需引入。

















