I am having trouble adding a chart legend to my d3js chart. Here is my current approach:
var legend = svg.append("g")
.attr("class", "legend")
.attr("x", w - 65)
.attr("y", 25)
.attr("height", 100)
.attr("width", 100);
legend.append("rect")
.attr("x", w - 65)
.attr("y", 25)
.attr("width", 10)
.attr("height", 10)
.style("fill", function(d) { return color_hash[dataset.indexOf(d)][1] });
legend.append("text")
.attr("x", w - 65)
.attr("y", 25)
.text(function(d) { return color_hash[dataset.indexOf(d)][0] + ": " + d; });
Then I am attempting to style the .legend
class:
.legend {
padding: 5px;
font: 10px sans-serif;
background: yellow;
box-shadow: 2px 2px 1px #888;
}
But I'm not having much luck.
Is anyone familiar with adding legends to charts able to provide the best way to do so? I am not finding many resources for this online.
Here is my entire graph: http://jsbin.com/ewiwag/2/edit
You need to bind data to the nodes (rectangles and text elements) that make up the legend.
Currently you get an error when trying to style rectangles:
Uncaught TypeError: Cannot read property '1' of undefined
The reason: there's no bound data
legend.append("rect")
/*...*/
.style("fill", function(d) {
// d <---- is undefined
return color_hash[dataset.indexOf(d)][1]
});
Notice that D3 focuses on data transformation and operates on selections. So, first select a set of nodes and then bind data
legend.selectAll('rect')
.data(dataset)
.enter()
Once you enter the selection with enter
, you can add nodes and apply properties dynamically. Notice that to avoid creating rectangles on top of others, when setting the y
property pass the i
counter and multiply it by an integer.
/*.....*/
.append("rect")
.attr("x", w - 65)
.attr("y", function(d, i){ return i * 20;})
.attr("width", 10)
.attr("height", 10)
.style("fill", function(d) {
var color = color_hash[dataset.indexOf(d)][1];
return color;
});
Here's the fixed example: http://jsbin.com/ubafur/3