d3.js Sankey diagram: rectangles fill color

lucastimmons picture lucastimmons · Oct 22, 2012 · Viewed 26.7k times · Source

So I am playing around with the d3.js Sankey diagram.

enter image description here

In this example (pictured above) color is defined using

var color = d3.scale.category20();

For each node there is a rectangle, and that rectangle is filled by altering the style:

.style("fill", function(d) {
    return d.color = color(d.name.replace(/ .*/, ""));
})

I'm looking for suggestions on using custom colors. If I wanted to use only say 6 colors, but have the node rectangle colors chosen based on a value in the .json file.

For example, lets say I wanted to show a snakey chart of teams in the NFL. The colours each represent which division the teams play in. So if they move to a different division, the color changes. And the nodes are created for every season. Something along those lines.

So is it possible to run the

node.append("rect")
    .attr("height", function(d) { return d.dy; })
    .attr("width", sankey.nodeWidth())
    .style("fill", function(d) {
        return d.color = color(d.name.replace(/ .*/, ""));
    })
    .style("stroke", function(d) {
        return d3.rgb(d.color).darker(2);
    })
   .append("title")
    .text(function(d) { return d.name + "\n" + format(d.value); });

with the color based on a value in the json file? I am thinking just an if statement, but is there an easier way? Could I just include the hex color code in the json?

Answer

imrane picture imrane · Oct 22, 2012

Alternatively, you could map the colors to the division explicitly with a d3 ordinal scale as mentioned in the documentation. See Colorbrewer at the bottom.

var color = d3.scale.ordinal()
    .domain(["foo", "bar", "baz"])
    .range(["#fff","#000","#333"]);

and then

.attr("fill", function(d) { return color(d.division); });