Search code examples
d3.jshierarchicalhierarchical-clustering

How to differentiate inner and leaf (final) nodes in a D3 dendogram


I used D3.js to generate a dendogram where the user will see the results of a clutering. However, to keep the display clean, I would like the parent nodes to be kept as simple as possible (no text, no circle).

This is how the data is currently displayed: http://i.imgur.com/Cz52Fhl.png

And this is an example of how I would like it to show (the orientation does not matter, what matters is that inner nodes have not text or circle): http://i.imgur.com/Oo2A0b7.png

The code...

// Compute the new tree layout.
      var nodes = tree.nodes(root).reverse(),
          links = tree.links(nodes);

      // Normalize for fixed-depth.
      nodes.forEach(function(d) { d.y = d.depth * 130; });

      // Update the nodes…
      var node = svg.selectAll("g.node")
          .data(nodes, function(d) { return d.id || (d.id = ++i); });

      // Enter any new nodes at the parent's previous position.
      var nodeEnter = node.enter().append("g")
          .attr("class", "node")
          .attr("transform", function(d) { return "translate(" + source.y0 + "," + source.x0 + ")"; })
          .on("click", click);

      nodeEnter.append("circle")
          .attr("r", 1e-6)
          .style("fill", function(d) { return d._children ? "lightsteelblue" : "#fff"; });

      nodeEnter.append("text")
          .attr("x", function(d) { return d.children || d._children ? -10 : 10; })
          .attr("dy", ".35em")
          .attr("text-anchor", function(d) { return d.children || d._children ? "end" : "start"; })
          .text(function(d) { return d.canonical; })
          .style("fill-opacity", 1e-6);

Solution

  • Is it that you would like the ability to add a label next to the leaf nodes (the ones on the far right), with no label for any intermediary node?

    If yes, there is is a live example at: http://bl.ocks.org/widged/5150104

    Whether the node is of type inner or leaf is defined by this part of the code

      .enter().append("svg:g")
            .attr("class", function(n) {
              if (n.children) {
                return "inner node"
              } else {
                return "leaf node"
              }
            })
    

    and later

    var endnodes =  vis.selectAll('g.leaf.node')
        .append("svg:text")
        ... skipping attributes ...
        .text(function(d) { return d.data.name; });