Улучшение Примера Последовательности D3 Sunburst
этой D3
пример послужил моей отправной точкой:
http://bl.ocks.org/kerryrodden/7090426
я хотел изменить данные для диаграммы, и я сделал следующий новый пример:
можно заметить по крайней мере две проблемы:
- легенда-это неправильно. Это потому, что это все еще содержит "жестко закодированные" имена из исходного примера.
- все узлы окрашены в черный цвет. Это связано с тем, что цветовая схема также "жестко закодирована" только для имен узлов из исходного примера.
Как улучшить оригинальный пример (или мой 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.