Улучшение Примера Последовательности D3 Sunburst

этой D3 пример послужил моей отправной точкой:

http://bl.ocks.org/kerryrodden/7090426

enter image description here


я хотел изменить данные для диаграммы, и я сделал следующий новый пример:

http://jsfiddle.net/ZGVK3/

enter image description here

можно заметить по крайней мере две проблемы:

  1. легенда-это неправильно. Это потому, что это все еще содержит "жестко закодированные" имена из исходного примера.
  2. все узлы окрашены в черный цвет. Это связано с тем, что цветовая схема также "жестко закодирована" только для имен узлов из исходного примера.

Как улучшить оригинальный пример (или мой jsfiddle, это не важно), так что легенда и окраски самостоятельно доводят до сведения, что для схемы?

1 ответов


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

Шаг 1. Создайте порядковую шкалу для цветов

вместо colors быть просто список имен цветов, жестко закодированных для конкретных имен, используйте d3.scale.ordinal() и выберите .range() для выбора цвета, которые вы хотите использовать. Например:

var colors = d3.scale.ordinal()
  .range(["#5687d1","#7b615c","#de783b","#6ab975","#a173d1","#bbbbbb"]);

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

в качестве ярлыка, вы можете использовать d3.scale.category20() чтобы позволить d3 выбрать диапазон 20 категориальных цветов для вас.

теперь при настройке цветов заливки для вашего path элемент дуги, а также сухари, вы бы просто использовать colors(d.name) вместо colors[d.name].

Шаг 2. Используйте свои данные для построения домена scale

на .domain() этого масштаба будет установлен, как только мы получим данные, так как это будет зависеть от списка уникальных имен, содержащихся в данных. Для этого мы можем перебирать данные и создавать массив уникальных имен. Вероятно, есть несколько способов сделать это, но вот один, который работает хорошо:

var uniqueNames = (function(a) {
  var output = [];
  a.forEach(function(d) {
    if (output.indexOf(d.name) === -1) {
      output.push(d.name);
    }
  });
  return output;
})(nodes);

это создает пустой массив, затем перебирает каждый элемент the nodes array и если имя узла еще не существует в новом массиве, оно добавляется.

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

colors.domain(uniqueNames);

Шаг 3. Используйте домен масштаба для создания легенды

поскольку легенда будет зависеть от домена, убедитесь, что drawLegend() функция вызывается после установки домена.

вы можете найти количество элементов в домен (для установки высота легенды) по телефону colors.domain().length. Тогда для легенды .data(), вы можете использовать сам домен. Наконец, чтобы установить цвет заливки для полей легенды, вы вызываете цветовую шкалу на d С каждого элемента домена name. Вот как эти три изменения в легенде выглядят на практике:

var legend = d3.select("#legend").append("svg:svg")
  .attr("width", li.w)
  .attr("height", colors.domain().length * (li.h + li.s));

var g = legend.selectAll("g")
  .data(colors.domain())
  .enter().append("svg:g")
  .attr("transform", function(d, i) {
     return "translate(0," + i * (li.h + li.s) + ")";
  });

g.append("svg:rect")
  .attr("rx", li.r)
  .attr("ry", li.r)
  .attr("width", li.w)
  .attr("height", li.h)
  .style("fill", function(d) { return colors(d); });

и это все. Надеюсь, это поможет.

вот обновленная JSFiddle.