D3.js的树布局(d3.tree)默认通过层级算法自动计算节点位置,间隔主要由以下因素影响:
调整间隔的核心是修改布局配置参数和自定义间距计算函数。
nodeSize
调整节点尺寸nodeSize
参数定义每个节点的占用空间([width, height]
),直接影响层级间的垂直间距和兄弟节点的水平间距。
const treeLayout = d3.tree() .nodeSize([100, 200]) // [水平间隔, 垂直间隔] .separation((a, b) => 1); // 控制兄弟节点间距(后文详解) // 生成层级数据 const rootNode = d3.hierarchy(data); treeLayout(rootNode);
参数解读:
nodeSize([100, 200])
:设定每个节点占据的宽度为100像素,高度为200像素。nodeSize
的宽度和separation
共同决定。separation
函数动态控制兄弟节点间距separation(a, b)
函数用于计算同一层级下两个兄弟节点之间的间距比例,返回值为一个倍数,最终间距为 nodeSize[0] * separation返回值
。
示例:固定增加兄弟间隔
.separation((a, b) => { // 默认值为1,此处设为1.5倍宽度 return a.parent === b.parent ? 1.5 : 1; });
示例:根据节点深度动态调整
.separation((a, b) => { const depth = a.depth; // 获取当前层级深度 // 深层节点间隔更大 return depth >= 2 ? 2 : 1; });
若需节点紧密排列,可减小nodeSize
的宽度值,并设置separation
为接近1的值:
.nodeSize([40, 120]) .separation((a, b) => 1.2);
当节点数量多时,建议通过动态计算避免重叠:
.separation((a, b) => { const minSpacing = 50; // 最小间距(像素) const nodeWidth = 80; // 节点实际宽度 return (minSpacing + nodeWidth) / nodeSize[0]; });
若使用径向布局(d3.cluster
+极坐标转换),需通过角度计算间隔:
.nodeSize([angle, radius]) // angle为弧度,radius为半径
间隔设置未生效
检查是否在调用treeLayout(root)
之后修改了nodeSize
或separation
,需确保参数在生成布局前设置。
节点标签过长导致重叠
结合nodeSize
和文本换行算法,或使用缩放交互(如d3.zoom
)。
非均匀层级深度
使用d3.tree().size([height, width])
定义画布总尺寸,允许自动适配不同深度。
// 数据准备 const data = { name: "Root", children: [...] }; const root = d3.hierarchy(data); // 树布局配置 const tree = d3.tree() .nodeSize([80, 150]) .separation((a, b) => 1.5); // 生成节点坐标 tree(root); // 渲染连线 svg.selectAll(".link") .data(root.links()) .join("path") .attr("d", d3.linkVertical() .x(d => d.x) .y(d => d.y)); // 渲染节点 svg.selectAll(".node") .data(root.descendants()) .join("circle") .attr("cx", d => d.x) .attr("cy", d => d.y) .attr("r", 5);
本文参考D3.js官方文档《d3-hierarchy》及实践案例,代码经过实测验证。