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

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的尺寸计算和布局偏移,确保所有节点都能容纳:

  1. 增大基础高度值,预留足够空间;
  2. 合并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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 22:38:12