H.RJ
H.RJ

Reputation: 91

How to avoid curved links in a d3 radial tree diagram?

I am working with this code to get a radial tree diagram for my data. However, I'd like to modify it to avoid curved links. Instead I am interested in linear straight connections. The curved links make the illustration to be less sophisticated specially when we have lower number of children nodes. For instance, you may look at the parent node and its links with the nodes on the first layer (circle). How can I use straight lines for these connections?

This is the part of the code I would like to modify to satisfy my needs:

    var link = g.selectAll(".link")
   .data(root.links())
    .enter().append("path")
     .attr("class", "link")
      .attr("d", d3.linkRadial()
      .angle(function(d) { return d.x; })
      .radius(function(d) { return d.y; }));

where function is currently defined as

 function radialPoint(x, y) {
  return [(y = +y) * Math.cos(x -= Math.PI / 2), y * Math.sin(x)];
} 

Thanks.

Upvotes: 2

Views: 1034

Answers (1)

Andrew Reid
Andrew Reid

Reputation: 38151

To get linear straight connections, don't use a path generator - d3.linkRadial (or d3.linkHorizontal etc) - use a line:

var link = g.selectAll(".link")
    .data(tree(root).links())
    .enter().append("line")
      .attr("class", "link")
      .attr("stroke","#ccc")
      .attr("x1", function(d) { return radialPoint(d.source.x,d.source.y)[0]; })
      .attr("y1", function(d) { return radialPoint(d.source.x,d.source.y)[1]; })
      .attr("x2", function(d) { return radialPoint(d.target.x,d.target.y)[0]; })
      .attr("y2", function(d) { return radialPoint(d.target.x,d.target.y)[1]; }) ;

This will keep your links straight, the snippet below should demonstrate this.

var data = { "name": "Root", "children": [ 
	{ "name": "A", "children": [ {"name": "A-1" }, {"name": "A-2" }, {"name":"A-3"}, {"name":"A-4"}, { "name":"A-5"} ] }, 
	{ "name": "B", "children": [ {"name": "B-1" } ] },
	{ "name": "C" },
	{ "name": "D", "children": [ {"name": "D-1" }, {"name": "D-2" }, {"name": "D-3", "children": [ {"name": "D-3-i"}, {"name":"D-3-ii"} ] } ] },
	{ "name": "E" },
	{ "name": "F" }
	] };

var width = 960;
var height = 500;

margin = {left: 100, top: 100, right: 50, bottom: 50}

var svg = d3.select("body").append("svg")
      .attr("width", width)
      .attr("height", height);
	  
var g = svg.append("g").attr('transform','translate('+ width/2 +','+ height/2 +')');

var root = d3.hierarchy(data);
	  
var tree = d3.tree()
    .size([2 * Math.PI, height/2]);

var link = g.selectAll(".link")
    .data(tree(root).links())
    .enter().append("line")
      .attr("class", "link")
	  .attr("stroke","#ccc")
      .attr("x1", function(d) { return radialPoint(d.source.x,d.source.y)[0]; })
      .attr("y1", function(d) { return radialPoint(d.source.x,d.source.y)[1]; })
	  .attr("x2", function(d) { return radialPoint(d.target.x,d.target.y)[0]; })
	  .attr("y2", function(d) { return radialPoint(d.target.x,d.target.y)[1]; })
		  ;

  var node = g.selectAll(".node")
    .data(root.descendants())
    .enter().append("g")
      .attr("class", function(d) { return "node" + (d.children ? " node--internal" : " node--leaf"); })
	  .attr("transform", function(d) { return "translate(" + radialPoint(d.x, d.y) + ")"; })

  node.append("circle")
      .attr("r", 2.5);
	  
  node.append("text")
     .text(function(d) { return d.data.name; })
	 .attr('y',-10)
	 .attr('x',-10)
	 .attr('text-anchor','middle');
	 
 

  function radialPoint(x, y) {
	return [(y = +y) * Math.cos(x -= Math.PI / 2), y * Math.sin(x)];
  }
		
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.5.0/d3.min.js"></script>

Upvotes: 2

Related Questions