D3 Flextree – Resizable Nodes

by Rajesh Danabal

HTML

<!DOCTYPE html>
<meta charset="utf-8" />
<title>D3 Flextree – Resizable Nodes</title>
<style>
  body {
    margin: 0;
    font-family: sans-serif;
    background: #0b0f14;
    color: #e6edf3;
  }
  svg {
    width: 100vw;
    height: 100vh;
    display: block;
  }
  .node rect {
    rx: 8;
    ry: 8;
    fill: #1f2937;
    stroke: #94a3b8;
    stroke-width: 1.25;
  }
  .node text {
    fill: #e6edf3;
    pointer-events: none;
    font-size: 12px;
  }
  .handle {
    fill: #93c5fd;
    stroke: #1e3a8a;
    stroke-width: 1;
    cursor: nwse-resize;
  }
  .link {
    fill: none;
    stroke: #475569;
    stroke-width: 1.25;
  }
</style>

<body>
  <svg id="svg"></svg>

  <!-- D3 + d3-flextree -->
  <script src="https://cdn.jsdelivr.net/npm/d3@7"></script>
  <script src="https://cdn.jsdelivr.net/npm/d3-flextree@2"></script>
  <script>
    // ---------- Utilities ----------
    const DEFAULT_W = 120;
    const DEFAULT_H = 60;

    function setDefaults(node, defaultW = DEFAULT_W, defaultH = DEFAULT_H) {
      if (node.w == null) node.w = defaultW;
      if (node.h == null) node.h = defaultH;
      if (node.children)
        node.children.forEach(c => setDefaults(c, defaultW, defaultH));
    }

    const getW = d =>
      typeof d.data.w === "number" ? d.data.w : DEFAULT_W;
    const getH = d =>
      typeof d.data.h === "number" ? d.data.h : DEFAULT_H;

    // ---------- Sample data ----------
    const data = {
      name: "Root",
      w: 120,
      h: 60,
      children: [
        {
          name: "Alpha",
          w: 120,
          h: 60,
          children: [
            { name: "A-1", w: 110, h: 50 },
            { name: "A-2", w: 140, h: 60 }
          ]
        },
        { name: "Beta", w: 140, h: 70 },
        { name: "Gamma", w: 160, h: 60 }
      ]
    };

    setDefaults(data);

    // ---------- Layout setup ----------
    const hGap = 30;
    const vGap = 30;

   ...