Home > Mobile >  D3JS Tree with Axis
D3JS Tree with Axis

Time:12-17

I'd like to know how to mix tree with axis in D3js (v5 ). My problem is that when I display my tree with nodes, links and labels, when I add an Axis, all labels disapear.

See this code snippet :

var treeData = {
  name: "Top Level",
  children: [
    {
      name: "Level 2: A",
      children: [{ name: "Son of A" }, { name: "Daughter of A" }]
    },
    { name: "Level 2: B" }
  ]
};

// set the dimensions and margins of the diagram
var margin = { top: 40, right: 90, bottom: 50, left: 90 },
  width = 660 - margin.left - margin.right,
  height = 500 - margin.top - margin.bottom;

// declares a tree layout and assigns the size
var treemap = d3.tree().size([width, height]);

//  assigns the data to a hierarchy using parent-child relationships
var nodes = d3.hierarchy(treeData);

// maps the node data to the tree layout
nodes = treemap(nodes);

// append the svg obgect to the body of the page
// appends a 'group' element to 'svg'
// moves the 'group' element to the top left margin
var svg = d3
    .select("body")
    .append("svg")
    .attr("width", width   margin.left   margin.right)
    .attr("height", height   margin.top   margin.bottom),
  g = svg
    .append("g")
    .attr("transform", "translate("   margin.left   ","   margin.top   ")");

var x = d3
  .scaleLinear()
  .domain([0, 100]) // This is what is written on the Axis: from 0 to 100
  .range([100, 800]);
//svg.call(d3.axisBottom(x));

// adds the links between the nodes
var link = g
  .selectAll(".link")
  .data(nodes.descendants().slice(1))
  .enter()
  .append("path")
  .attr("class", "link")
  .attr("d", function (d) {
    return (
      "M"  
      d.x  
      ","  
      d.y  
      "C"  
      d.x  
      ","  
      (d.y   d.parent.y) / 2  
      " "  
      d.parent.x  
      ","  
      (d.y   d.parent.y) / 2  
      " "  
      d.parent.x  
      ","  
      d.parent.y
    );
  });

// adds each node as a group
var node = g
  .selectAll(".node")
  .data(nodes.descendants())
  .enter()
  .append("g")
  .attr("class", function (d) {
    return "node"   (d.children ? " node--internal" : " node--leaf");
  })
  .attr("transform", function (d) {
    return "translate("   d.x   ","   d.y   ")";
  });

// adds the circle to the node
node.append("circle").attr("r", 10);

// adds the text to the node
node
  .append("text")
  .attr("dy", ".35em")
  .attr("y", function (d) {
    return d.children ? -20 : 20;
  })
  .style("text-anchor", "middle")
  .text(function (d) {
    return d.data.name;
  });
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<style>
      .node circle {
        fill: #fff;
        stroke: steelblue;
        stroke-width: 3px;
      }

      .node text {
        font: 12px sans-serif;
      }

      .link {
        fill: none;
        stroke: #ccc;
      stroke-width: 2px;
      }
    
</style>

If you uncomment the line #43 and run again, you will see that labels disapear and I don't understand why.

Thank you for your help

CodePudding user response:

Always append a new group for your axis:

svg.append('g').call(d3.axisBottom(x));

The axis constructor operates on the element its called on. You don't want that to be an element containing other things.

  • Related