如何在D3.js中独立设置连线的起点与终点位置?
解决方法
要让连线从盒子右侧出发,连接到子盒子的左侧,你可以直接为连线的起点(源节点)和终点(目标节点)定义不同坐标,替代统一的x()和y()方法:
修改连线部分的代码:
svg.append('g') // link .attr('fill', 'none') .attr('stroke', 'black') .attr('stroke-width', 0.1) .selectAll() .data(root.links()) .join('path') .attr('d', d3.linkHorizontal() // 起点:源节点盒子的右侧(x坐标加上盒子宽度) .source(d => [d.source.depth * box_spacing + box_width, d.source.data.y]) // 终点:目标节点盒子的左侧(使用原始x坐标) .target(d => [d.target.depth * box_spacing, d.target.data.y]) );
原理说明
d3.linkHorizontal()的source()和target()方法可接收每个连线对象(包含source父节点和target子节点),直接返回对应点的[x, y]坐标数组。- 源节点起点偏移盒子宽度(
box_width),对应盒子右侧边缘;目标节点直接使用原始x坐标,对应盒子左侧边缘。
修改后的完整代码:
<!DOCTYPE html> <div id="container"></div> <script type="module"> import * as d3 from 'https://cdn.jsdelivr.net/npm/d3@7/+esm'; const data = { name: 'a', y: 2, children: [ { name: 'b', y: 1 }, { name: 'c', y: 3, children: [ { name: 'd', y: 2 }, { name: 'e', y: 4 }, ]} ]} const root = d3.hierarchy(data); const width = 400; const height = 200; const box_width = 3; const box_spacing = 5; const svg = d3.create('svg') .attr('width', width) .attr('height', height) .attr('viewBox', [0, 0, 20, 10]) .attr('style', 'max-width: 100%; height: auto; font: 1px mono;'); const node = svg.append('g') .selectAll() .data(root.descendants()) .join('g') .attr('transform', (d) => `translate(${d.depth * box_spacing},${d.data.y})`); node.append('rect') .attr('width', box_width) .attr('height', 1) .attr('fill', '#ccc') .attr('y', -0.5); node.append('text') .text((d) => d.data.name) .attr('y', 0.4); svg.append('g') // link .attr('fill', 'none') .attr('stroke', 'black') .attr('stroke-width', 0.1) .selectAll() .data(root.links()) .join('path') .attr('d', d3.linkHorizontal() .source(d => [d.source.depth * box_spacing + box_width, d.source.data.y]) .target(d => [d.target.depth * box_spacing, d.target.data.y]) ); container.append(svg.node()); </script>
内容的提问来源于stack exchange,提问作者roipoussiere
相关产品推荐
相关产品推荐

