Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

d3.js adding legend to multiline series chart

How would one add a legend to the multiline series chart? I tried but am not getting any legend to display.

The block here:

http://bl.ocks.org/3884955

has a flaw when the various series converge to the same point, like zero. All the labels will be overlayed on each other. Instead of going for these labels, a traditional legend would be useful.

I tried adding this

var legend = svg.append("g")
.attr("class", "legend")
.attr("height", 100)
.attr("width", 100)
.attr('transform', 'translate(-20,50)');    

legend.selectAll('rect')
  .datum(function(d) { return {name: d.name, value: d.values[d.values.length - 1]}; })
  .append("rect")
  .attr("x", width)
  .attr("y", function(d, i){ return i *  20;})
  .attr("width", 10)
  .attr("height", 10)
  .style("fill", function(d) { 
    return color.domain(d3.keys(d[0]).filter(function(key) { return key !== "day"; }));
  });

legend.selectAll('text')
  .datum(function(d) { return {name: d.name, value: d.values[d.values.length - 1]}; })
  .append("text")
  .attr("x", width)
  .attr("y", function(d, i){ return i *  20 + 9;})
  .text(function(d) {
  return d.name;
  });

to the end of the code, the key names (d.name) match how my data is formatted, but it does not display. At one point it showed all black boxes to the right of the graph so that means I am close but I am missing something important

any insight appreciated

like image 217
CQM Avatar asked Feb 08 '13 15:02

CQM


1 Answers

Here is a fixed & refactored version of your code.

    var legend = svg.selectAll('g')
        .data(cities)
        .enter()
      .append('g')
        .attr('class', 'legend');

    legend.append('rect')
        .attr('x', width - 20)
        .attr('y', function(d, i){ return i *  20;})
        .attr('width', 10)
        .attr('height', 10)
        .style('fill', function(d) { 
          return color(d.name);
        });

    legend.append('text')
        .attr('x', width - 8)
        .attr('y', function(d, i){ return (i *  20) + 9;})
        .text(function(d){ return d.name; });

You need to use enter(), but enter() and exit() methods cannot be used with datum(). Quoting from the d3 wiki

selection.datum([value])

Gets or sets the bound data for each selected element. Unlike the selection.data method, this method does not compute a join (and thus does not compute enter and exit selections).

like image 72
Cihan Keser Avatar answered Nov 15 '22 16:11

Cihan Keser