From 695a999452e89e55cffcf2a81536084dbcbb7e21 Mon Sep 17 00:00:00 2001 From: Mike Bostock Date: Fri, 24 Aug 2018 08:34:01 -0700 Subject: [PATCH] Add d3.interpolateHue; fixes #36. --- README.md | 4 +++ d3-interpolate.sublime-project | 16 +++++++----- index.js | 1 + src/hue.js | 9 +++++++ test/hue-test.js | 48 ++++++++++++++++++++++++++++++++++ 5 files changed, 72 insertions(+), 6 deletions(-) create mode 100644 src/hue.js create mode 100644 test/hue-test.js diff --git a/README.md b/README.md index fb22105..c26acd5 100644 --- a/README.md +++ b/README.md @@ -216,6 +216,10 @@ var interpolator = d3.interpolateRgb.gamma(2.2)("purple", "orange"); See Eric Brasseur’s article, [Gamma error in picture scaling](https://web.archive.org/web/20160112115812/http://www.4p8.com/eric.brasseur/gamma.html), for more on gamma correction. +# d3.interpolateHue(a, b) [<>](https://github.com/d3/d3-interpolate/blob/master/src/hue.js "Source") + +Returns an interpolator between the two hue angles *a* and *b*. If either hue is NaN, the opposing value is used. The shortest path between hues is used. The return value of the interpolator is a number in [0, 360). + ### Splines Whereas standard interpolators blend from a starting value *a* at *t* = 0 to an ending value *b* at *t* = 1, spline interpolators smoothly blend multiple input values for *t* in [0,1] using piecewise polynomial functions. Only cubic uniform nonrational [B-splines](https://en.wikipedia.org/wiki/B-spline) are currently supported, also known as basis splines. diff --git a/d3-interpolate.sublime-project b/d3-interpolate.sublime-project index 6e0c2d4..858fc1c 100644 --- a/d3-interpolate.sublime-project +++ b/d3-interpolate.sublime-project @@ -2,12 +2,16 @@ "folders": [ { "path": ".", - "file_exclude_patterns": [ - "*.sublime-workspace" - ], - "folder_exclude_patterns": [ - "build" - ] + "file_exclude_patterns": ["*.sublime-workspace"], + "folder_exclude_patterns": ["build"] + } + ], + "build_systems": [ + { + "name": "yarn test", + "cmd": ["yarn", "test"], + "file_regex": "\\((...*?):([0-9]*):([0-9]*)\\)", + "working_dir": "$project_path" } ] } diff --git a/index.js b/index.js index 6e05c67..fe2e492 100644 --- a/index.js +++ b/index.js @@ -4,6 +4,7 @@ export {default as interpolateBasis} from "./src/basis"; export {default as interpolateBasisClosed} from "./src/basisClosed"; export {default as interpolateDate} from "./src/date"; export {default as interpolateDiscrete} from "./src/discrete"; +export {default as interpolateHue} from "./src/hue"; export {default as interpolateNumber} from "./src/number"; export {default as interpolateObject} from "./src/object"; export {default as interpolateRound} from "./src/round"; diff --git a/src/hue.js b/src/hue.js new file mode 100644 index 0000000..be5e189 --- /dev/null +++ b/src/hue.js @@ -0,0 +1,9 @@ +import {hue} from "./color"; + +export default function(a, b) { + var i = hue(+a, +b); + return function(t) { + var x = i(t); + return x - 360 * Math.floor(x / 360); + }; +} diff --git a/test/hue-test.js b/test/hue-test.js new file mode 100644 index 0000000..aedee3d --- /dev/null +++ b/test/hue-test.js @@ -0,0 +1,48 @@ +var tape = require("tape"), + interpolate = require("../"); + +tape("interpolateHue(a, b) interpolate numbers", function(test) { + var i = interpolate.interpolateHue("10", "20"); + test.strictEqual(i(0.0), 10); + test.strictEqual(i(0.2), 12); + test.strictEqual(i(0.4), 14); + test.strictEqual(i(0.6), 16); + test.strictEqual(i(0.8), 18); + test.strictEqual(i(1.0), 20); + test.end(); +}); + +tape("interpolateHue(a, b) returns a if b is NaN", function(test) { + var i = interpolate.interpolateHue(10, NaN); + test.equal(i(0.0), 10); + test.equal(i(0.5), 10); + test.equal(i(1.0), 10); + test.end(); +}); + +tape("interpolateHue(a, b) returns b if a is NaN", function(test) { + var i = interpolate.interpolateHue(NaN, 20); + test.equal(i(0.0), 20); + test.equal(i(0.5), 20); + test.equal(i(1.0), 20); + test.end(); +}); + +tape("interpolateHue(a, b) returns NaN if both a and b are NaN", function(test) { + var i = interpolate.interpolateHue(NaN, NaN); + test.equal(isNaN(i(0.0)), true); + test.equal(isNaN(i(0.5)), true); + test.equal(isNaN(i(1.0)), true); + test.end(); +}); + +tape("interpolateHue(a, b) uses the shortest path", function(test) { + var i = interpolate.interpolateHue(10, 350); + test.equal(i(0.0), 10); + test.equal(i(0.2), 6); + test.equal(i(0.4), 2); + test.equal(i(0.6), 358); + test.equal(i(0.8), 354); + test.equal(i(1.0), 350); + test.end(); +});