Skip to content

Instantly share code, notes, and snippets.

@fgassert
Forked from mbostock/.block
Last active August 29, 2015 14:00
Show Gist options
  • Save fgassert/11304263 to your computer and use it in GitHub Desktop.
Save fgassert/11304263 to your computer and use it in GitHub Desktop.

D3 2.10.0 adds support for CIE L*a*b* and HCL. These colors spaces are designed with perception in mind. RGB and HSL interpolation can cause unintentional grouping due to parts of the color space appearing more visually similar; L*a*b* and HCL, in contrast, are perceptually-uniform. For more information, see Gregor Aisch’s post How To Avoid Equidistant HSV Colors and Drew Skau’s post Dear NASA: No More Rainbow Color Scales, Please.

You can create L*a*b* or HCL colors using d3.lab or d3.hcl. For example:

var steelblue = d3.lab(52, -4, -32);
var steelblue = d3.hcl(-97, 32, 52);

You can also convert from RGB or HSL:

var steelblue = d3.lab("#4682b4");
var steelblue = d3.hcl("hsl(207, 44%, 49%)");

Best of all, you can use d3.interpolateLab or d3.interpolateHcl in conjunction with quantitative scales and transitions:

var color = d3.scale.linear()
    .range(["steelblue", "brown"])
    .interpolate(d3.interpolateHcl);

L*a*b* and HCL interpolation is a convenient way to implement color scales that are comparable in quality to Colorbrewer.

<!DOCTYPE html>
<meta charset="utf-8">
<style>
body {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
}
</style>
<body>
<script src="https://raw.github.com/mbostock/d3/2.10.0/d3.v2.min.js"></script>
<script>
var interpolators = {
"HSL": d3.interpolateHsl,
"HCL": d3.interpolateHcl,
"Lab": d3.interpolateLab,
"RGB": d3.interpolateRgb
};
var width = 960,
height = 500;
var y = d3.scale.ordinal()
.domain(d3.keys(interpolators))
.rangeRoundBands([0, height], .1);
var values = d3.range(960 - 28);
var x = d3.scale.ordinal()
.domain(values)
.rangeRoundBands([14, width - 14]);
var color = d3.scale.linear()
.domain([0, values.length - 1])
.range(["hsl(62,100%,90%)", "hsl(228,30%,20%)"]);
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
var g = svg.selectAll("g")
.data(d3.entries(interpolators))
.enter().append("g")
.attr("transform", function(d) { return "translate(0," + y(d.key) + ")"; });
g.each(function(d) {
color.interpolate(d.value);
d3.select(this).selectAll("rect")
.data(values)
.enter().append("rect")
.attr("x", x)
.attr("width", x.rangeBand())
.attr("height", y.rangeBand)
.style("fill", color);
});
g.append("text")
.attr("x", 28)
.attr("y", y.rangeBand() / 2)
.attr("dy", ".35em")
.text(function(d) { return d.key; });
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment