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

D3.js多brush区域交互:刷取新区域时如何清除其他区域选中态并避免栈溢出

问题原因

你遇到的调用栈溢出是无限事件循环导致的:

  • 你在start和brush事件的回调里调用d3.brush().clear清除所有区域的选中状态,这个清除操作本身会再次触发brush事件
  • 新触发的brush事件又会进入回调执行清除逻辑,无限循环最终撑爆调用栈
  • 同时你把当前正在操作的brush区域也一并清除了,不符合你只清其他区域的需求
解决方案

只需要修改brush事件回调逻辑即可:

  1. 先判断事件触发来源:如果是代码自动触发的事件(没有e.sourceEvent),直接终止逻辑,避免循环
  2. 清除选中时跳过当前正在操作的brush区域,只清理其他区域
  3. 可根据需要单独监听end事件处理刷选后的业务逻辑,避免频繁触发冗余执行
修正后的完整代码
<script src="https://d3js.org/d3.v7.min.js" charset="utf-8"></script>
let width = 2000;
let height = 1200;
let svg = d3.select("body")
  .append("svg")
  .attr("width", width)
  .attr("height", height);

for (let j = 0; j < 3; j++) {
  let rx = 400 * j,
    ry = 100,
    rw = 300,
    rh = 300;
  let g = svg.append("g")
    .attr("x", rx).attr("y", ry)
    .attr("width", rw).attr("height", rh);

  g.append("rect")
    .attr("x", rx).attr("y", ry)
    .attr("width", rw).attr("height", rh)
    .attr("fill", "white")
    .attr("stroke", "black");

  g.call(d3.brush()
    .extent([
      [rx, ry],
      [rx + rw, ry + rh]
    ])
    .on("start brush end", function(e) {
      // 代码触发的brush事件直接返回,避免循环
      if (!e.sourceEvent) return;
      // 清除除当前区域外的所有brush选中
      svg.selectAll("g").filter((d,i,n) => n[i] !== this).call(d3.brush().clear);
      // 业务逻辑,获取当前刷选范围
      let extent = e.selection;
      // 在这里写你的后续处理代码
    })
  );
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.23 20:06:01