D3.js добавляет легенду к многострочной диаграмме серии

Как добавить легенду в многострочную диаграмму? Я пробовал, но у меня не появляется никаких легенд.

Блок здесь:

http://bl.ocks.org/3884955

имеет недостаток, когда различные ряды сходятся к одной и той же точке, как и нуль. Все ярлыки будут накладываться друг на друга. Вместо того, чтобы идти на эти ярлыки, было бы полезно использовать традиционную легенду.

Я попытался добавить это

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;
  });

до конца кода имена ключей (d.name) соответствуют тому, как мои данные отформатированы, но они не отображаются. В какой-то момент он показал все черные прямоугольники справа от графика, поэтому означает, что я близок, но мне не хватает чего-то важного.

любое понимание оценено

Ответ 1

Здесь - это исправленная и реорганизованная версия вашего кода.

    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; });

Вам нужно использовать enter(), но enter() и exit() методы не могут использоваться с datum(). Цитата из d3 wiki

selection.datum([значение])

Получает или задает связанные данные для каждого выбранного элемента. В отличие от метода selection.data, этот метод не вычисляет объединение (и, следовательно, не вычисляет выбор входа и выхода).

Ответ 2

Кажется, вам не хватает функции .enter() после вызова функции .datum().

legend.selectAll('rect')

  .datum(function(d) { return {name: d.name, value: d.values[d.values.length - 1]}; })

  .enter() // <======

  .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"; }));

Перед добавлением "rect" вы должны использовать функцию enter(), чтобы увидеть точное описание Нажмите здесь