Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

D3.js - How can I prevent Circles & Text Overlapping

For each json a circle is created and x & y are randomly put out

for(var d = 0; d<json.length; d++){
circlexloc[d] = ((Math.random()*2*r)-r);
circleyloc[d] = ((Math.random()*2*r)-r);
};

Declaring a circle variable, whilst setting attributes & animation

var circle = svg.selectAll("circle").data(json)

circle.enter().append('circle')

Animation

circle.transition()
  .duration(1000)
  .attr("fill", "blue")
  .attr('opacity',0.6)
  .attr('r', 5)

  .attr("cx", function(d, i) {return circlexloc[i] })
  .attr("cy", function(d, i) {return circleyloc[i] });

circle.exit().transition().duration(1000)
  .attr('opacity',0)
  .attr("r",0)
  .remove();

Attach the technology to the circles

 var text = svg.selectAll('text')
text.data(json)
.enter().append("svg:text")
.style("font-size", "10px")
.text(function(d) { return d.TechName; })
.transition().duration(1000) 
.attr('opacity', 1)       
.attr("x", function (d, i) { return (circlexloc[i]+6)})
.attr("y", function (d, i) { return (circleyloc[i]+4)});

});

At the moment at times the tend to over lap each other. How can I prevent this? Suggestions & examples will be appreciated - thanks.

like image 724
user1701622 Avatar asked Oct 17 '12 21:10

user1701622


1 Answers

You have a couple of different options, depending on what exactly you are going after.

One way is to use a force directed layout which applies forces to the nodes to make sure that they don't overlap after reaching a steady state (note that they may overlap as they are getting to the steady state). You can see an example of this at http://bl.ocks.org/1377729. Note that you can fully customize what the nodes look like and eliminate the lines.

I created an example of the forced based layout at http://jsfiddle.net/xwZjN/2/. With a force based layout you need to add the nodes first.

   force
       .nodes(nodes)
       .start();

And then update their locations for each force recalculation.

   force.on("tick", function() {

     text.attr("x", function(d) { return d.x + 6; })
         .attr("y", function(d) { return d.y + 4; });           

     node.attr("cx", function(d) { return d.x; })
         .attr("cy", function(d) { return d.y; });
   });

The other option is to use a pack layout like the example at http://bl.ocks.org/1628131. This layout will pack the circles tightly together and ensure that they don't overlap.

like image 53
Bill Avatar answered Oct 23 '22 11:10

Bill