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

如何使用D3/JavaScript降低拖拽绘制点的频率?

解决D3.js拖拽绘制点速率过高的问题

要降低mousemove事件中绘制点的频率,核心思路是限制绘制动作的触发次数,常见的两种实现方式如下:

方式一:时间间隔节流

通过记录上次绘制的时间,仅当当前时间与上次绘制时间的间隔达到设定阈值时,才执行绘制操作。比如要降到原速率的1/10,可设置间隔为100ms(mousemove通常每秒触发约100次左右)。

修改后的代码如下:

// 定义变量记录上次绘制时间
let lastDrawTime = 0;

svg.on("mousedown", mousedown)
  .on("mouseup", mouseup);

function mousedown() {
  // 鼠标按下时立即绘制点,并重置时间
  const new_x = xScale.invert(d3.pointer(event)[0]);
  const new_y = yScale.invert(d3.pointer(event)[1]);
  svg.append("circle")
    .data([{x: new_x, y: new_y}])
    .attr("cx", d => xScale(d.x))
    .attr("cy", d => yScale(d.y))
    .attr("r", "3");
  
  lastDrawTime = Date.now();
  svg.on("mousemove", mousemove);
}

function mousemove() {
  const now = Date.now();
  // 100ms间隔对应原速率的1/10,改成50ms就是1/5速率
  if (now - lastDrawTime < 100) return;
  
  const new_x = xScale.invert(d3.pointer(event)[0]);
  const new_y = yScale.invert(d3.pointer(event)[1]);
  svg.append("circle")
    .data([{x: new_x, y: new_y}])
    .attr("cx", d => xScale(d.x))
    .attr("cy", d => yScale(d.y))
    .attr("r", "3"); 
  
  lastDrawTime = now;
}

function mouseup() {
  svg.on("mousemove", null);
}

方式二:计数节流

通过计数器记录mousemove触发次数,仅当计数器达到指定倍数时才绘制点,之后重置计数器。比如要降到原速率的1/10,就每10次触发绘制一次。

修改后的代码如下:

// 定义变量记录触发次数
let moveCounter = 0;

svg.on("mousedown", mousedown)
  .on("mouseup", mouseup);

function mousedown() {
  const new_x = xScale.invert(d3.pointer(event)[0]);
  const new_y = yScale.invert(d3.pointer(event)[1]);
  svg.append("circle")
    .data([{x: new_x, y: new_y}])
    .attr("cx", d => xScale(d.x))
    .attr("cy", d => yScale(d.y))
    .attr("r", "3");
  
  moveCounter = 0;
  svg.on("mousemove", mousemove);
}

function mousemove() {
  moveCounter++;
  // 每10次触发绘制一次,改成5就是1/5速率
  if (moveCounter % 10 !== 0) return;
  
  const new_x = xScale.invert(d3.pointer(event)[0]);
  const new_y = yScale.invert(d3.pointer(event)[1]);
  svg.append("circle")
    .data([{x: new_x, y: new_y}])
    .attr("cx", d => xScale(d.x))
    .attr("cy", d => yScale(d.y))
    .attr("r", "3"); 
}

function mouseup() {
  svg.on("mousemove", null);
}

说明:两种方式各有优劣——时间间隔节流能保证绘制的均匀性,不受mousemove触发频率波动影响;计数节流则严格按照原触发次数的比例降低频率,适合对比例精度要求高的场景。

内容的提问来源于stack exchange,提问作者jtr13

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 18:15:17