d3.js Sankey diagram: rectangles fill color
Asked Answered
E

3

6

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?

Enabling answered 22/10, 2012 at 7:23 Comment(0)
A
6

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.

Ashton answered 22/10, 2012 at 9:27 Comment(1)
Thank you. This is what I was thinking. Based on what I am doing, this will work perfectly. .style("fill", function(d) { return d.color; }) is now pulling in a color from the .json file associated with each node.Enabling
L
26

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); });
Lalo answered 22/10, 2012 at 14:5 Comment(1)
Thanks for this. I got it to work, but based on what I am doing, pulling colors from Json is easier. But this is going to be very, very helpful in the future.Enabling
A
6

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.

Ashton answered 22/10, 2012 at 9:27 Comment(1)
Thank you. This is what I was thinking. Based on what I am doing, this will work perfectly. .style("fill", function(d) { return d.color; }) is now pulling in a color from the .json file associated with each node.Enabling
M
1

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;})
Molotov answered 23/7, 2017 at 14:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.