此D3
示例作为我的起点:
http://bl.ocks.org/kerryrodden/7090426
我想更改提供图表的数据,并制作了以下新示例:
人们可以注意到至少两个问题:
如何改进原始示例(或我的jsfiddle,无关紧要),以便图例和着色可以自动调整为图表的数据?
答案 0 :(得分:10)
您可以使用序数比例将颜色映射到不同的节点名称。实现它只需要对现有代码进行一些小的更改。
不要让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]
。
这个比例的.domain()
将在我们拥有数据后设置,因为它将取决于数据中包含的唯一名称列表。为此,我们可以遍历数据,并创建一个唯一名称的数组。可能有几种方法可以做到这一点,但这是一个运作良好的方法:
var uniqueNames = (function(a) {
var output = [];
a.forEach(function(d) {
if (output.indexOf(d.name) === -1) {
output.push(d.name);
}
});
return output;
})(nodes);
这将创建一个空数组,然后循环遍历nodes
数组的每个元素,如果新数组中已经存在节点的名称,则会添加该数组。
然后你可以简单地将新数组设置为色标的域:
colors.domain(uniqueNames);
由于图例将依赖于域,因此请确保在设置域后调用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。