Reputation: 181
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
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