Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

D3.js charts - Show legend in two rows

Tags:

svg

d3.js

I have 10 legend elements that I want to show in two rows on top of my D3.js chart. I have tried the following

legend.append("rect").attr("width", 20).attr("height", 15).style("fill", function(d) {
return color(d.packageName);
});

legend.append("text").attr("dx", +25).attr("dy", "0.8em").style("text-anchor","front").style("fill", "#666").text(function(d) {
return d.packageName;
});

var margin = {
 top: 30,
 right: 20,
 bottom: 30,
 left: 40
};

d3.selectAll(".legend").each(function(d, i) {
  return d3.selectAll(".legend").attr("transform", i < 6 ? function(d, i) {
  return "translate(" + ((i * 100) + (diameter / 10) - 25) + "," + (+margin.top * 2) +")";
  } : function(d, i) {
  return "translate(" + ((i * 100) + (diameter / 10) - 25) + "," + (+margin.top * 4) +")";
 });
 });

My goal was to change the y coordinate if the "i" counter went over 5 so that the legend elements appear in 2 rows of 5. But the above code shows all legend elements in the second row. I'm sure I'm missing something very simple here!

like image 803
Ansh Avatar asked Sep 06 '25 17:09

Ansh


1 Answers

My solution: put everything into the "enter" method, and compute the offsets.

legend = svg.selectAll(".legend").data(data).enter().append("g")
   .attr("class", "legend")
   .attr( "transform", function(d,i) { 
        xOff = (i % 4) * 50
        yOff = Math.floor(i  / 4) * 10
        return "translate(" + xOff + "," + yOff + ")" 
} );

Consequently, you can delete the entire "selectAll" and "each" portion at the bottom.

Updated Fiddle: http://jsfiddle.net/v7mkg/1/

Side-effect; this particular implementation could create many rows, but that's not at the heart of the issue.

like image 52
cmonkey Avatar answered Sep 10 '25 09:09

cmonkey