Skip to content

Commit

Permalink
Replace d3.interpolateBind with named parameters.
Browse files Browse the repository at this point in the history
Rather than have interpolators take optional arguments, and then require
d3-scale to bind those optional arguments, configurable interpolators (of which
cubehelix is the only one, so far) now expose named configuration methods.

    var i = d3.interpolateCubehelix("red", "blue", 3); // BEFORE
    var i = d3.interpolateCubehelix.gamma(3)("red", "blue"); // AFTER

This makes the usage of optional parameters self-documenting.

Related d3/d3-ease#13.
  • Loading branch information
mbostock committed Feb 1, 2016
1 parent 7150b84 commit 70ebb63
Show file tree
Hide file tree
Showing 9 changed files with 204 additions and 80 deletions.
19 changes: 9 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ If you use NPM, `npm install d3-interpolate`. Otherwise, download the [latest re

```html
<script src="https://d3js.org/d3-color.v0.3.min.js"></script>
<script src="https://d3js.org/d3-interpolate.v0.4.min.js"></script>
<script src="https://d3js.org/d3-interpolate.v0.5.min.js"></script>
```

In a vanilla environment, a `d3_interpolate` global is exported. [Try d3-interpolate in your browser.](https://tonicdev.com/npm/d3-interpolate)
Expand Down Expand Up @@ -163,31 +163,30 @@ Returns an HCL color space interpolator between the two colors *a* and *b*. The

Like [interpolateHcl](#interpolateHcl), but does not use the shortest path between hues.

<a name="interpolateCubehelix" href="#interpolateCubehelix">#</a> d3.<b>interpolateCubehelix</b>(<i>a</i>, <i>b</i>[, <i>gamma</i>])
<a name="interpolateCubehelix" href="#interpolateCubehelix">#</a> d3.<b>interpolateCubehelix</b>(<i>a</i>, <i>b</i>)

<img src="https://raw.githubusercontent.com/d3/d3-interpolate/master/img/cubehelix.png" width="100%" height="40" alt="cubehelix">

Or, with a gamma of 3.0 to emphasize high-intensity values:
Or, with a [gamma](#cubehelix_gamma) of 3.0 to emphasize high-intensity values:

<img src="https://raw.githubusercontent.com/d3/d3-interpolate/master/img/cubehelixGamma.png" width="100%" height="40" alt="cubehelixGamma">

Returns a Cubehelix color space interpolator between the two colors *a* and *b* using the specified *gamma*. If *gamma* is not specified, it defaults to 1.0. The colors *a* and *b* need not be in Cubehelix; they will be converted to Cubehelix using [color.cubehelix](https://github.com/d3/d3-color#cubehelix). If either color’s hue or saturation is NaN, the opposing color’s channel value is used. The shortest path between hues is used. The return value of the interpolator is a hexadecimal RGB string.
Returns a Cubehelix color space interpolator between the two colors *a* and *b* using a configurable [gamma](#cubehelix_gamma). If the gamma is not specified, it defaults to 1.0. The colors *a* and *b* need not be in Cubehelix; they will be converted to Cubehelix using [color.cubehelix](https://github.com/d3/d3-color#cubehelix). If either color’s hue or saturation is NaN, the opposing color’s channel value is used. The shortest path between hues is used. The return value of the interpolator is a hexadecimal RGB string.

<a name="interpolateCubehelixLong" href="#interpolateCubehelixLong">#</a> d3.<b>interpolateCubehelixLong</b>(<i>a</i>, <i>b</i>[, <i>gamma</i>])
<a name="interpolateCubehelixLong" href="#interpolateCubehelixLong">#</a> d3.<b>interpolateCubehelixLong</b>(<i>a</i>, <i>b</i>)

<img src="https://raw.githubusercontent.com/d3/d3-interpolate/master/img/cubehelixLong.png" width="100%" height="40" alt="cubehelixLong">

Or, with a gamma of 3.0 to emphasize high-intensity values:
Or, with a [gamma](#cubehelix_gamma) of 3.0 to emphasize high-intensity values:

<img src="https://raw.githubusercontent.com/d3/d3-interpolate/master/img/cubehelixGammaLong.png" width="100%" height="40" alt="cubehelixGammaLong">

Like [interpolateCubehelix](#interpolateCubehelix), but does not use the shortest path between hues.

<a name="interpolateBind" href="#interpolateBind">#</a> d3.<b>interpolateBind</b>(<i>type</i>[, <i>parameters…</i>])
<a name="cubehelix_gamma" href="#cubehelix_gamma">#</a> <i>cubehelix</i>.<b>gamma</b>(<i>gamma</i>)

A convenience function for binding zero or more *parameters* to the specified interpolation function *type*. If no *parameters* are specified, this function simply returns *type*. The returned function takes two arguments *a* and *b* and passes any optional *parameters* to the underlying function *type*. For example, the following statements are equivalent:
Returns a new Cubehelix interpolator factory using the specified *gamma*. For example, to interpolate from red to blue with a gamma of 3.0:

```js
d3.interpolateBind(d3.interpolateCubehelix, 3)("purple", "orange");
d3.interpolateCubehelix("purple", "orange", 3);
var interpolate = d3.interpolateCubehelix.gamma(3.0)("red", "blue");
```
1 change: 0 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,3 @@ export {default as interpolateHcl} from "./src/hcl";
export {default as interpolateHclLong} from "./src/hclLong";
export {default as interpolateCubehelix} from "./src/cubehelix";
export {default as interpolateCubehelixLong} from "./src/cubehelixLong";
export {default as interpolateBind} from "./src/bind";
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "d3-interpolate",
"version": "0.4.1",
"version": "0.5.0",
"description": "Interpolate numbers, colors, strings, arrays, objects, whatever!",
"keywords": [
"d3",
Expand All @@ -24,7 +24,7 @@
"pretest": "mkdir -p build && node -e 'process.stdout.write(\"var version = \\\"\" + require(\"./package.json\").version + \"\\\"; export * from \\\"../index\\\"; export {version};\");' > build/bundle.js && rollup -f umd -g d3-color:d3_color -n d3_interpolate -o build/d3-interpolate.js -- build/bundle.js",
"test": "faucet `find test -name '*-test.js'` && eslint index.js src",
"prepublish": "npm run test && uglifyjs build/d3-interpolate.js -c -m -o build/d3-interpolate.min.js && rm -f build/d3-interpolate.zip && zip -j build/d3-interpolate.zip -- LICENSE README.md build/d3-interpolate.js build/d3-interpolate.min.js",
"postpublish": "VERSION=`node -e 'console.log(require(\"./package.json\").version)'`; git push && git tag -am \"Release $VERSION.\" v${VERSION} && git push --tags && cp build/d3-interpolate.js ../d3.github.com/d3-interpolate.v0.4.js && cp build/d3-interpolate.min.js ../d3.github.com/d3-interpolate.v0.4.min.js && cd ../d3.github.com && git add d3-interpolate.v0.4.js d3-interpolate.v0.4.min.js && git commit -m \"d3-interpolate ${VERSION}\" && git push"
"postpublish": "VERSION=`node -e 'console.log(require(\"./package.json\").version)'`; git push && git tag -am \"Release $VERSION.\" v${VERSION} && git push --tags && cp build/d3-interpolate.js ../d3.github.com/d3-interpolate.v0.5.js && cp build/d3-interpolate.min.js ../d3.github.com/d3-interpolate.v0.5.min.js && cd ../d3.github.com && git add d3-interpolate.v0.5.js d3-interpolate.v0.5.min.js && git commit -m \"d3-interpolate ${VERSION}\" && git push"
},
"dependencies": {
"d3-color": "~0.3.4"
Expand Down
16 changes: 0 additions & 16 deletions src/bind.js

This file was deleted.

43 changes: 25 additions & 18 deletions src/cubehelix.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,27 @@
import {cubehelix} from "d3-color";
import {cubehelix as color} from "d3-color";
import deltaHue from "./deltaHue";

export default function(a, b, gamma) {
gamma = gamma == null ? 1 : +gamma;
a = cubehelix(a);
b = cubehelix(b);
var ah = isNaN(a.h) ? b.h : a.h,
as = isNaN(a.s) ? b.s : a.s,
al = a.l,
bh = isNaN(b.h) ? 0 : deltaHue(b.h, ah),
bs = isNaN(b.s) ? 0 : b.s - as,
bl = b.l - al;
return function(t) {
a.h = ah + bh * t;
a.s = as + bs * t;
a.l = al + bl * Math.pow(t, gamma);
return a + "";
};
}
export default (function gamma(y) {
y = +y;

function cubehelix(a, b) {
a = color(a);
b = color(b);
var ah = isNaN(a.h) ? b.h : a.h,
as = isNaN(a.s) ? b.s : a.s,
al = a.l,
bh = isNaN(b.h) ? 0 : deltaHue(b.h, ah),
bs = isNaN(b.s) ? 0 : b.s - as,
bl = b.l - al;
return function(t) {
a.h = ah + bh * t;
a.s = as + bs * t;
a.l = al + bl * Math.pow(t, y);
return a + "";
};
}

cubehelix.gamma = gamma;

return cubehelix;
})(1);
43 changes: 25 additions & 18 deletions src/cubehelixLong.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,26 @@
import {cubehelix} from "d3-color";
import {cubehelix as color} from "d3-color";

export default function(a, b, gamma) {
gamma = gamma == null ? 1 : +gamma;
a = cubehelix(a);
b = cubehelix(b);
var ah = isNaN(a.h) ? b.h : a.h,
as = isNaN(a.s) ? b.s : a.s,
al = a.l,
bh = isNaN(b.h) ? 0 : b.h - ah,
bs = isNaN(b.s) ? 0 : b.s - as,
bl = b.l - al;
return function(t) {
a.h = ah + bh * t;
a.s = as + bs * t;
a.l = al + bl * Math.pow(t, gamma);
return a + "";
};
}
export default (function gamma(y) {
y = +y;

function cubehelix(a, b) {
a = color(a);
b = color(b);
var ah = isNaN(a.h) ? b.h : a.h,
as = isNaN(a.s) ? b.s : a.s,
al = a.l,
bh = isNaN(b.h) ? 0 : b.h - ah,
bs = isNaN(b.s) ? 0 : b.s - as,
bl = b.l - al;
return function(t) {
a.h = ah + bh * t;
a.s = as + bs * t;
a.l = al + bl * Math.pow(t, y);
return a + "";
};
}

cubehelix.gamma = gamma;

return cubehelix;
})(1);
15 changes: 0 additions & 15 deletions test/bind-test.js

This file was deleted.

72 changes: 72 additions & 0 deletions test/cubehelix-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
var tape = require("tape"),
color = require("d3-color"),
interpolate = require("../");

tape("interpolateCubehelix(a, b) converts a and b to Cubehelix colors", function(test) {
test.equal(interpolate.interpolateCubehelix("steelblue", "brown")(0), color.rgb("steelblue") + "");
test.equal(interpolate.interpolateCubehelix("steelblue", color.hcl("brown"))(1), color.rgb("brown") + "");
test.equal(interpolate.interpolateCubehelix("steelblue", color.rgb("brown"))(1), color.rgb("brown") + "");
test.end();
});

tape("interpolateCubehelix(a, b) interpolates in Cubehelix and returns an RGB hexadecimal string", function(test) {
test.equal(interpolate.interpolateCubehelix("steelblue", "#f00")(0.2), "#5864da");
test.end();
});

tape("interpolateCubehelix.gamma(3)(a, b) returns the expected values", function(test) {
test.equal(interpolate.interpolateCubehelix.gamma(3)("steelblue", "#f00")(0.2), "#606be4");
test.end();
});

tape("interpolateCubehelix.gamma(g) coerces the specified gamma to a number", function(test) {
test.equal(interpolate.interpolateCubehelix.gamma({valueOf: function() { return 3; }})("steelblue", "#f00")(0.2), "#606be4");
test.end();
});

tape("interpolateCubehelix(a, b) is equivalent to interpolateCubehelix.gamma(1)(a, b)", function(test) {
var i0 = interpolate.interpolateCubehelix.gamma(1)("purple", "orange"),
i1 = interpolate.interpolateCubehelix("purple", "orange");
test.equal(i1(0.0), i0(0.0));
test.equal(i1(0.2), i0(0.2));
test.equal(i1(0.4), i0(0.4));
test.equal(i1(0.6), i0(0.6));
test.equal(i1(0.8), i0(0.8));
test.equal(i1(1.0), i0(1.0));
test.end();
});

tape("interpolateCubehelix(a, b) uses the shortest path when interpolating hue difference greater than 180°", function(test) {
var i = interpolate.interpolateCubehelix("purple", "orange");
test.equal(i(0.0), "#800080");
test.equal(i(0.2), "#d0017f");
test.equal(i(0.4), "#ff115d");
test.equal(i(0.6), "#ff342b");
test.equal(i(0.8), "#ff6905");
test.equal(i(1.0), "#ffa500");
test.end();
});

tape("interpolateCubehelix(a, b) uses a’s hue when b’s hue is undefined", function(test) {
test.equal(interpolate.interpolateCubehelix("#f60", color.hcl(NaN, NaN, 0))(0.5), "#a22900");
test.equal(interpolate.interpolateCubehelix("#6f0", color.hcl(NaN, NaN, 0))(0.5), "#03ad00");
test.end();
});

tape("interpolateCubehelix(a, b) uses b’s hue when a’s hue is undefined", function(test) {
test.equal(interpolate.interpolateCubehelix(color.hcl(NaN, NaN, 0), "#f60")(0.5), "#a22900");
test.equal(interpolate.interpolateCubehelix(color.hcl(NaN, NaN, 0), "#6f0")(0.5), "#03ad00");
test.end();
});

tape("interpolateCubehelix(a, b) uses a’s chroma when b’s chroma is undefined", function(test) {
test.equal(interpolate.interpolateCubehelix("#ccc", color.hcl(NaN, NaN, 0))(0.5), "#666666");
test.equal(interpolate.interpolateCubehelix("#f00", color.hcl(NaN, NaN, 0))(0.5), "#930000");
test.end();
});

tape("interpolateCubehelix(a, b) uses b’s chroma when a’s chroma is undefined", function(test) {
test.equal(interpolate.interpolateCubehelix(color.hcl(NaN, NaN, 0), "#ccc")(0.5), "#666666");
test.equal(interpolate.interpolateCubehelix(color.hcl(NaN, NaN, 0), "#f00")(0.5), "#930000");
test.end();
});
71 changes: 71 additions & 0 deletions test/cubehelixLong-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
var tape = require("tape"),
color = require("d3-color"),
interpolate = require("../");

tape("interpolateCubehelixLong(a, b) converts a and b to Cubehelix colors", function(test) {
test.equal(interpolate.interpolateCubehelixLong("steelblue", "brown")(0), color.rgb("steelblue") + "");
test.equal(interpolate.interpolateCubehelixLong("steelblue", color.hcl("brown"))(1), color.rgb("brown") + "");
test.equal(interpolate.interpolateCubehelixLong("steelblue", color.rgb("brown"))(1), color.rgb("brown") + "");
test.end();
});

tape("interpolateCubehelixLong(a, b) interpolates in Cubehelix and returns an RGB hexadecimal string", function(test) {
test.equal(interpolate.interpolateCubehelixLong("steelblue", "#f00")(0.2), "#5864da");
test.end();
});

tape("interpolateCubehelixLong.gamma(3)(a, b) returns the expected values", function(test) {
test.equal(interpolate.interpolateCubehelixLong.gamma(3)("steelblue", "#f00")(0.2), "#606be4");
test.end();
});

tape("interpolateCubehelixLong.gamma(g) coerces the specified gamma to a number", function(test) {
test.equal(interpolate.interpolateCubehelixLong.gamma({valueOf: function() { return 3; }})("steelblue", "#f00")(0.2), "#606be4");
test.end();
});

tape("interpolateCubehelixLong(a, b) is equivalent to interpolateCubehelixLong.gamma(1)(a, b)", function(test) {
var i0 = interpolate.interpolateCubehelixLong.gamma(1)("purple", "orange"),
i1 = interpolate.interpolateCubehelixLong("purple", "orange");
test.equal(i1(0.0), i0(0.0));
test.equal(i1(0.2), i0(0.2));
test.equal(i1(0.4), i0(0.4));
test.equal(i1(0.6), i0(0.6));
test.equal(i1(0.8), i0(0.8));
test.equal(i1(1.0), i0(1.0));
test.end();
});
tape("interpolateCubehelixLong(a, b) uses the longest path when interpolating hue difference greater than 180°", function(test) {
var i = interpolate.interpolateCubehelixLong("purple", "orange");
test.equal(i(0.0), "#800080");
test.equal(i(0.2), "#3f36ea");
test.equal(i(0.4), "#0097d9");
test.equal(i(0.6), "#00df53");
test.equal(i(0.8), "#4fdb00");
test.equal(i(1.0), "#ffa500");
test.end();
});

tape("interpolateCubehelixLong(a, b) uses a’s hue when b’s hue is undefined", function(test) {
test.equal(interpolate.interpolateCubehelixLong("#f60", color.hcl(NaN, NaN, 0))(0.5), "#a22900");
test.equal(interpolate.interpolateCubehelixLong("#6f0", color.hcl(NaN, NaN, 0))(0.5), "#03ad00");
test.end();
});

tape("interpolateCubehelixLong(a, b) uses b’s hue when a’s hue is undefined", function(test) {
test.equal(interpolate.interpolateCubehelixLong(color.hcl(NaN, NaN, 0), "#f60")(0.5), "#a22900");
test.equal(interpolate.interpolateCubehelixLong(color.hcl(NaN, NaN, 0), "#6f0")(0.5), "#03ad00");
test.end();
});

tape("interpolateCubehelixLong(a, b) uses a’s chroma when b’s chroma is undefined", function(test) {
test.equal(interpolate.interpolateCubehelixLong("#ccc", color.hcl(NaN, NaN, 0))(0.5), "#666666");
test.equal(interpolate.interpolateCubehelixLong("#f00", color.hcl(NaN, NaN, 0))(0.5), "#930000");
test.end();
});

tape("interpolateCubehelixLong(a, b) uses b’s chroma when a’s chroma is undefined", function(test) {
test.equal(interpolate.interpolateCubehelixLong(color.hcl(NaN, NaN, 0), "#ccc")(0.5), "#666666");
test.equal(interpolate.interpolateCubehelixLong(color.hcl(NaN, NaN, 0), "#f00")(0.5), "#930000");
test.end();
});

0 comments on commit 70ebb63

Please sign in to comment.