Присутствует дополнительная легенда - PullRequest
0 голосов
/ 02 ноября 2019

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

var color_hash = {  0 : ["Male", "blue"],
                    1 : ["Female", "pink"]}

var legend = svg.append("g")
            .attr("class", "legend")
            .attr("x", width - 65)
            .attr("y", 25)
            .attr("height", 100)
            .attr("width", 100);

legend.selectAll('g').data(data)
      .enter()
      .append('g')
      .each(function(d, i) {
        var g = d3.select(this);
        g.append("rect")
         .attr("x", width - 65)
         .attr("y", i*25)
         .attr("width", 10)
         .attr("height", 10)
         .style("fill", color_hash[String(i)][1]);
        g.append("text")
         .attr("x", width - 50)
         .attr("y", i * 25 + 8)
         .attr("height", 30)
         .attr("width", 100)
         .style("fill", color_hash[String(i)[1]])
         .text(color_hash[String(i)][0]);

      });

черный прямоугольник является дополнительным:

enter image description here

1 Ответ

1 голос
/ 02 ноября 2019

С циклом ввода / обновления / выхода в D3 вы обычно хотите иметь массив данных, который содержит один элемент для каждого элемента, который вы хотите нарисовать. У вас есть:

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

Мы используем data для визуализации color_hash, это не идеально.

Для одного вы хотите построить только 2 элемента, я могу сказать, что длинаиз data не менее 3:

Вы создаете пустой g с помощью:

var legend = svg.append("g")

Затем выбираете дочерние элементы g этого:

legend.selectAll('g')

Поскольку их нет, это пустой выбор. Затем вы присваиваете данные этому выбору и вводите новые элементы HTML / SVG:

legend.selectAll('g')
  .data(data)
  .enter()
  .append('g')

Поскольку legend является пустым выбором, выбор ввода создаст один элемент HTML / SVG для каждого элемента в массиве данных. ,После входа (и / или выхода) количество элементов HTML / SVG должно быть равно количеству элементов в массиве данных. Таким образом, в data должно быть как минимум 3 элемента (может быть больше , если создано дополнительных элементов, но они выходят за границы SVG / контейнера. Это также объясняет, почему в третьем блоке нетцвет или текст: цветовой хэш не имеет значений с ключом 2 или более).

D3 - создает элементы из данных, как правило, в отношении один к одному между элементами и элементами. Чтобы создать нашу легенду, массив данных должен быть тем, что мы хотим построить . Как следствие, нам нужно преобразовать цветовой хэш в массив:

var legendData = [
  {name: "A", color:"crimson"},
  {name: "B", color:"steelblue"}
];

Теперь мы просто передаем это в selection.data()

И, поскольку мы теперь привязываем нужные данныеЧтобы нарисовать записи легенды, мы также можем упростить код, вместо:

 .style("fill", color_hash[String(i)][1]);

и

 .text(color_hash[String(i)][0]);

Мы можем просто использовать:

  .style("fill",d.color);

и

  .text(d.name);

Это дает нам:

var color_hash = {  0 : ["Male", "blue"],
                    1 : ["Female", "pink"]}

var width = 300;
var height = 200;

var svg = d3.select("svg")
  .attr("width",width)
  .attr("height",height);

var legendData = [
  {name:"A",color:"crimson"},
  {name:"B",color:"steelblue"}
]

var legend = svg.append("g")

legend.selectAll('g')
  .data(legendData)
  .enter()
  .append('g')
  .each(function(d, i) {
        var g = d3.select(this);
        g.append("rect")
         .attr("x", width - 65)
         .attr("y", i*25+25)
         .attr("width", 10)
         .attr("height", 10)
         .style("fill", d.color);
        g.append("text")
         .attr("x", width - 50)
         .attr("y", i * 25 + 33)
         .attr("height", 30)
         .attr("width", 100)
         .style("fill", d.color)
         .text(d.name);

      });
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg></svg>

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

...