6

This D3 example served as my starting point:

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

enter image description here


I wanted to change data that feeds the diagram, and I made following new example:

http://jsfiddle.net/ZGVK3/

enter image description here

One can notice at least two problems:

  1. Legend is wrong. This is because it still contains 'hardcoded' names from original example.
  2. All nodes are colored black. This is because the color scheme is also 'hardcoded' only for node names from original example.

How to improve the original example (or my jsfiddle, it doesn't matter) so that legend and coloring are self-adjusted to the data that feeds the diagram?

4

1 回答 1

10

您可以使用序数比例将颜色映射到不同的节点名称。实现它只需要对现有代码进行一些小的更改。

第 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. 使用您的数据构建规模域

一旦我们有了数据,就会设置这个.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);

步骤 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

于 2014-07-06T06:07:17.850 回答