D3.js多brush区域交互:刷取新区域时如何清除其他区域选中态并避免栈溢出
问题原因
你遇到的调用栈溢出是无限事件循环导致的:
- 你在
start和brush事件的回调里调用d3.brush().clear清除所有区域的选中状态,这个清除操作本身会再次触发brush事件 - 新触发的
brush事件又会进入回调执行清除逻辑,无限循环最终撑爆调用栈 - 同时你把当前正在操作的brush区域也一并清除了,不符合你只清其他区域的需求
解决方案
只需要修改brush事件回调逻辑即可:
- 先判断事件触发来源:如果是代码自动触发的事件(没有
e.sourceEvent),直接终止逻辑,避免循环 - 清除选中时跳过当前正在操作的brush区域,只清理其他区域
- 可根据需要单独监听
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
相关产品推荐
相关产品推荐

