techer
techer

Reputation: 181

D3 Tree Graph - How to transition links when using straight line, not diagonal

I am working with this JS Fiddle: http://jsfiddle.net/f1nzagyw/

I want to change the example from diagonal to straight lines, which I have been able to do but when I click on a node to expand or shorten the graph, the old links aren't being removed from the graph, so I end up with multiple links. Can someone please advise on how I can transition the original links, using straight lines, with the transitioning nodes? It seemed to change when I moved from diagonal to straight lines.

I added the lineFunction and used it in the links as you can see in the fiddle,:

     var lineFunction = d3.svg.line()
        .x(function(d) { return d.x; })
        .y(function(d) { return d.y; })
        .interpolate("linear");

I also appended the "line" and the x/y coordinates:

 var link = svg.selectAll("path.link")
      .data(links)
      .enter().append("line")
      .attr("class", "link")
      .attr("x1", function(d) { return d.source.y; })
      .attr("y1", function(d) { return d.source.x; })
      .attr("x2", function(d) { return d.target.y; })
      .attr("y2", function(d) { return d.target.x; });

Also, what's the best way to keep the links behind the nodes, so that the links run behind the nodes, not in front? I thought I just needed to put the code for the links above the nodes but that doesn't seem to be working.

Any help is appreciated. Thanks

Upvotes: 1

Views: 2334

Answers (1)

Cyril Cherian
Cyril Cherian

Reputation: 32327

Problem 1

The old links are not getting updated

You are doing:

var link = svg.selectAll("path.link")
      .data(links)

This is wrong because there is no path DOM there is a line DOM so you are selection is wrong.

You should be doing:

var link = svg.selectAll(".link")
    .data(links)

Problem 2

The best way to keep the links behind the nodes:

First create links and then create nodes so now the links will appear behind nodes.

//create link first
link.enter().append("line")
    .attr("class", "link")
    .attr("x1", function(d) {
      return d.source.y;
    })
    .attr("y1", function(d) {
      return d.source.x;
    })
    .attr("x2", function(d) {
      return d.target.y;
    })
    .attr("y2", function(d) {
      return d.target.x;
    });

  // Transition links to their new position.
  link.transition()
    .duration(duration)
    .attr("d", lineFunction)
    .attr("x1", function(d) {
      return d.source.y;
    })
    .attr("y1", function(d) {
      return d.source.x;
    })
    .attr("x2", function(d) {
      return d.target.y;
    })
    .attr("y2", function(d) {
      return d.target.x;
    });;

  // Transition exiting nodes to the parent's new position.
  link.exit()
    .remove();
   //create nodes
  // 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);

working code here

EDIT

To ensure that nodes are always on the top make two groups.

var svglink = svg.append("g");//add links inside this group
var svgnode = svg.append("g");//add nodes inside this group

Now when you make links do this to ensure that they are on below the nodes.

  // Update the links…
  var link = svglink.selectAll(".link")
    .data(links)

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

working example here

Upvotes: 3

Related Questions