Question

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?

Was it helpful?

Solution

Sounds like you want to include the colour in the JSON in this case. You can include it in any way that the browser recognises, e.g. as a name ("white") or hex ("#fff"). See the SVG spec for a full list of supported colour specifications.

OTHER TIPS

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); });

Replace const color = d3.scaleOrdinal(d3.schemeCategory20); with:

const color = d3.scaleOrdinal() 
.domain(["Crude oil","Natural gas",...])
.range(["#FD3E35","#FFCB06",...]);

And stay with:

.style('fill', (d,i) => {
  d.color = color(d.name.replace(/ .*/, ''));
  return d.color;})
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top