D3.js树形图节点缺失求助:最后一个节点Pippo未显示
D3.js树形图节点Pippo未显示的问题修复
我正在通过简单示例学习D3.js,目标是基于JSON数据结构绘制树形图。编写最小示例后,树形图连线已正常绘制,但最后一个节点Pippo未显示,请问代码中缺少了什么?
原代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Collapsible Tree with D3.js</title> <script src="https://d3js.org/d3.v7.min.js"></script> <style> .node { cursor: pointer; } .node circle { fill: #fff; stroke: steelblue; stroke-width: 3px; } .node text { font: 12px sans-serif; } .link { fill: none; stroke: #ccc; stroke-width: 2px; } </style> </head> <body> <script> // Sample JSON data const treeData = { "name": "Root", "children": [ { "name": "Child 1", "children": [ { "name": "Child 1.1", "children": [ { "name":"Pippo" } ] }, { "name": "Child 1.2" } ] }, { "name": "Child 2", "children": [ { "name": "Child 2.1" }, { "name": "Child 2.2" } ] } ] }; // ************** Generate the tree diagram ***************** var margin = {top: 20, right: 120, bottom: 20, left: 120}, width = 960 - margin.right - margin.left, height = 500 - margin.top - margin.bottom; var i = 0; // Create SVG container const svg = d3.select("body").append("svg") .attr("width", width) .attr("height", height) .append("g") .attr("transform", "translate(50, 20)"); // Create hierarchical data structure const root = d3.hierarchy(treeData); var tree = d3.tree().size([height, width]); tree(root); // Create links const link = svg.selectAll(".link") .data(root.links()) .enter().append("path") .attr("class", "link") .attr("d", d3.linkHorizontal() .x(d => d.y) .y(d => d.x) ); // Create nodes const node = svg.selectAll(".node") .data(root.descendants()) .enter().append("g") .attr("class", "node") .attr("transform", d => `translate(${d.y},${d.x})`); // Debug print of structure console.log("Nodes are: "); console.log(node); // Add circles to nodes node.append("circle") .attr("r", 10); // Add text to nodes node.append("text") .attr("y", -20) .attr("x", -16) .attr("text-anchor", d => ("start")) .text(d => d.data.name); </script> </body> </html>
问题原因
节点Pippo未显示是因为SVG容器的可视空间不足,导致该节点被裁剪:
- 计算后的SVG高度为
500 - 20 - 20 = 460,但横向树形图布局后,Pippo节点的垂直位置(对应D3树形图的x坐标)超出了这个高度范围; - 额外给内部
g元素添加的translate(50,20)进一步压缩了底部可用空间,最终节点被挤出可视区域。
修复方案
调整SVG的尺寸计算和布局偏移,确保所有节点都能容纳:
- 增大基础高度值,预留足够空间;
- 合并margin和translate的偏移设置,避免重复占用空间。
修复后的完整代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Collapsible Tree with D3.js</title> <script src="https://d3js.org/d3.v7.min.js"></script> <style> .node { cursor: pointer; } .node circle { fill: #fff; stroke: steelblue; stroke-width: 3px; } .node text { font: 12px sans-serif; } .link { fill: none; stroke: #ccc; stroke-width: 2px; } </style> </head> <body> <script> // Sample JSON data const treeData = { "name": "Root", "children": [ { "name": "Child 1", "children": [ { "name": "Child 1.1", "children": [ { "name":"Pippo" } ] }, { "name": "Child 1.2" } ] }, { "name": "Child 2", "children": [ { "name": "Child 2.1" }, { "name": "Child 2.2" } ] } ] }; // ************** Generate the tree diagram ***************** var margin = {top: 40, right: 120, bottom: 40, left: 120}, width = 960 - margin.right - margin.left, height = 600 - margin.top - margin.bottom; // 增大基础高度 // Create SVG container const svg = d3.select("body").append("svg") .attr("width", width + margin.left + margin.right) // 包含margin的总宽度 .attr("height", height + margin.top + margin.bottom) // 包含margin的总高度 .append("g") .attr("transform", `translate(${margin.left}, ${margin.top})`); // 用margin做偏移 // Create hierarchical data structure const root = d3.hierarchy(treeData); var tree = d3.tree().size([height, width]); tree(root); // Create links const link = svg.selectAll(".link") .data(root.links()) .enter().append("path") .attr("class", "link") .attr("d", d3.linkHorizontal() .x(d => d.y) .y(d => d.x) ); // Create nodes const node = svg.selectAll(".node") .data(root.descendants()) .enter().append("g") .attr("class", "node") .attr("transform", d => `translate(${d.y},${d.x})`); // Add circles to nodes node.append("circle") .attr("r", 10); // Add text to nodes node.append("text") .attr("y", -20) .attr("x", -16) .attr("text-anchor", "start") .text(d => d.data.name); </script> </body> </html>
内容的提问来源于stack exchange,提问作者Pich
相关产品推荐
相关产品推荐

