Skip to content

Commit

Permalink
Merge branch 'opacity'
Browse files Browse the repository at this point in the history
  • Loading branch information
mbostock committed Feb 3, 2016
2 parents 659001f + b6dc436 commit e0f5fdf
Show file tree
Hide file tree
Showing 25 changed files with 362 additions and 417 deletions.
2 changes: 2 additions & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ ecmaFeatures:
env:
es6: true
browser: true
node: true

extends:
"eslint:recommended"

rules:
no-cond-assign: 0
no-floating-decimal: 2
26 changes: 13 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,16 @@ The returned function `i` is called an *interpolator*. Given a starting value *a
You can interpolate more than just numbers. To find the perceptual midpoint between steelblue and brown:

```js
d3.interpolateLab("steelblue", "brown")(0.5); // "#8e5c6d"
d3.interpolateLab("steelblue", "brown")(0.5); // "rgb(142, 92, 109)"
```

Here’s a more elaborate example demonstrating type inference used by [interpolate](#interpolate):

```js
var i = d3.interpolate({colors: ["red", "blue"]}, {colors: ["white", "black"]});
i(0.0); // {colors: ["#ff0000", "#0000ff"]}
i(0.5); // {colors: ["#ff8080", "#000080"]}
i(1.0); // {colors: ["#ffffff", "#000000"]}
i(0.0); // {colors: ["rgb(255, 0, 0)", "rgb(0, 0, 255)"]}
i(0.5); // {colors: ["rgb(255, 128, 128)", "rgb(0, 0, 128)"]}
i(1.0); // {colors: ["rgb(255, 255, 255)", "rgb(0, 0, 0)"]}
```

Note that the generic value interpolator detects not only nested objects and arrays, but also color strings and numbers embedded in strings!
Expand All @@ -34,7 +34,7 @@ Note that the generic value interpolator detects not only nested objects and arr
If you use NPM, `npm install d3-interpolate`. Otherwise, download the [latest release](https://github.com/d3/d3-interpolate/releases/latest). The released bundle supports AMD, CommonJS, and vanilla environments. Create a custom build using [Rollup](https://github.com/rollup/rollup) or your preferred bundler. You can also load directly from [d3js.org](https://d3js.org):

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

Expand Down Expand Up @@ -97,21 +97,21 @@ Returns an interpolator between the two strings *a* and *b*. The string interpol

For each number embedded in *b*, the interpolator will attempt to find a corresponding number in *a*. If a corresponding number is found, a numeric interpolator is created using [interpolateNumber](#interpolateNumber). The remaining parts of the string *b* are used as a template: the static parts of the string *b* remain constant for the interpolation, with the interpolated numeric values embedded in the template.

For example, if *a* is `"300 12px sans-serif"`, and *b* is `"500 36px Comic-Sans"`, two embedded numbers are found. The remaining static parts of the string are a space between the two numbers (`" "`), and the suffix (`"px Comic-Sans"`). The result of the interpolator at *t* = .5 is `"400 24px Comic-Sans"`.
For example, if *a* is `"300 12px sans-serif"`, and *b* is `"500 36px Comic-Sans"`, two embedded numbers are found. The remaining static parts of the string are a space between the two numbers (`" "`), and the suffix (`"px Comic-Sans"`). The result of the interpolator at *t* = 0.5 is `"400 24px Comic-Sans"`.

<a name="interpolateArray" href="#interpolateArray">#</a> d3.<b>interpolateArray</b>(<i>a</i>, <i>b</i>)

Returns an interpolator between the two arrays *a* and *b*. Internally, an array template is created that is the same length in *b*. For each element in *b*, if there exists a corresponding element in *a*, a generic interpolator is created for the two elements using [interpolate](#interpolate). If there is no such element, the static value from *b* is used in the template. Then, for the given parameter *t*, the template’s embedded interpolators are evaluated. The updated array template is then returned.

For example, if *a* is the array `[0, 1]` and *b* is the array `[1, 10, 100]`, then the result of the interpolator for *t* = .5 is the array `[.5, 5.5, 100]`.
For example, if *a* is the array `[0, 1]` and *b* is the array `[1, 10, 100]`, then the result of the interpolator for *t* = 0.5 is the array `[0.5, 5.5, 100]`.

Note: **no defensive copy** of the template array is created; modifications of the returned array may adversely affect subsequent evaluation of the interpolator. No copy is made for performance reasons; interpolators are often part of the inner loop of [animated transitions](https://github.com/d3/d3-transition).

<a name="interpolateObject" href="#interpolateObject">#</a> d3.<b>interpolateObject</b>(<i>a</i>, <i>b</i>)

Returns an interpolator between the two objects *a* and *b*. Internally, an object template is created that has the same properties as *b*. For each property in *b*, if there exists a corresponding property in *a*, a generic interpolator is created for the two elements using [interpolate](#interpolate). If there is no such property, the static value from *b* is used in the template. Then, for the given parameter *t*, the template's embedded interpolators are evaluated and the updated object template is then returned.

For example, if *a* is the object `{x: 0, y: 1}` and *b* is the object `{x: 1, y: 10, z: 100}`, the result of the interpolator for *t* = .5 is the object `{x: .5, y: 5.5, z: 100}`.
For example, if *a* is the object `{x: 0, y: 1}` and *b* is the object `{x: 1, y: 10, z: 100}`, the result of the interpolator for *t* = 0.5 is the object `{x: 0.5, y: 5.5, z: 100}`.

Object interpolation is particularly useful for *dataspace interpolation*, where data is interpolated rather than attribute values. For example, you can interpolate an object which describes an arc in a pie chart, and then use d3.svg.arc to compute the new SVG path data.

Expand All @@ -135,13 +135,13 @@ Or, with a corrected [gamma](#interpolate_gamma) of 2.2:

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

Returns an RGB color space interpolator between the two colors *a* and *b* with a configurable [gamma](#interpolate_gamma). If the gamma is not specified, it defaults to 1.0. The colors *a* and *b* need not be in RGB; they will be converted to RGB using [color.rgb](https://github.com/d3/d3-color#rgb). The return value of the interpolator is a hexadecimal RGB string.
Returns an RGB color space interpolator between the two colors *a* and *b* with a configurable [gamma](#interpolate_gamma). If the gamma is not specified, it defaults to 1.0. The colors *a* and *b* need not be in RGB; they will be converted to RGB using [color.rgb](https://github.com/d3/d3-color#rgb). The return value of the interpolator is an RGB string.

<a name="interpolateHsl" href="#interpolateHsl">#</a> d3.<b>interpolateHsl</b>(<i>a</i>, <i>b</i>)

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

Returns an HSL color space interpolator between the two colors *a* and *b*. The colors *a* and *b* need not be in HSL; they will be converted to HSL using [color.hsl](https://github.com/d3/d3-color#hsl). 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 an HSL color space interpolator between the two colors *a* and *b*. The colors *a* and *b* need not be in HSL; they will be converted to HSL using [color.hsl](https://github.com/d3/d3-color#hsl). 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 an RGB string.

<a name="interpolateHslLong" href="#interpolateHslLong">#</a> d3.<b>interpolateHslLong</b>(<i>a</i>, <i>b</i>)

Expand All @@ -153,13 +153,13 @@ Like [interpolateHsl](#interpolateHsl), but does not use the shortest path betwe

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

Returns a Lab color space interpolator between the two colors *a* and *b*. The colors *a* and *b* need not be in Lab; they will be converted to Lab using [color.lab](https://github.com/d3/d3-color#lab). The return value of the interpolator is a hexadecimal RGB string.
Returns a Lab color space interpolator between the two colors *a* and *b*. The colors *a* and *b* need not be in Lab; they will be converted to Lab using [color.lab](https://github.com/d3/d3-color#lab). The return value of the interpolator is an RGB string.

<a name="interpolateHcl" href="#interpolateHcl">#</a> d3.<b>interpolateHcl</b>(<i>a</i>, <i>b</i>)

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

Returns an HCL color space interpolator between the two colors *a* and *b*. The colors *a* and *b* need not be in HCL; they will be converted to HCL using [color.hcl](https://github.com/d3/d3-color#hcl). If either color’s hue or chroma 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 an HCL color space interpolator between the two colors *a* and *b*. The colors *a* and *b* need not be in HCL; they will be converted to HCL using [color.hcl](https://github.com/d3/d3-color#hcl). If either color’s hue or chroma is NaN, the opposing color’s channel value is used. The shortest path between hues is used. The return value of the interpolator is an RGB string.

<a name="interpolateHclLong" href="#interpolateHclLong">#</a> d3.<b>interpolateHclLong</b>(<i>a</i>, <i>b</i>)

Expand All @@ -175,7 +175,7 @@ Or, with a [gamma](#interpolate_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 a configurable [gamma](#interpolate_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.
Returns a Cubehelix color space interpolator between the two colors *a* and *b* using a configurable [gamma](#interpolate_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 an RGB string.

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

Expand Down
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "d3-interpolate",
"version": "0.5.1",
"version": "0.5.2",
"description": "Interpolate numbers, colors, strings, arrays, objects, whatever!",
"keywords": [
"d3",
Expand All @@ -22,12 +22,12 @@
},
"scripts": {
"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",
"test": "faucet `find test -name '*-test.js'` && eslint index.js src test",
"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.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"
"d3-color": "~0.4.0"
},
"devDependencies": {
"faucet": "0.0",
Expand Down
29 changes: 29 additions & 0 deletions src/color.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import constant from "./constant";

function linear(a, d) {
return function(t) {
return a + t * d;
};
}

function exponential(a, b, y) {
return a = Math.pow(a, y), b = Math.pow(b, y) - a, y = 1 / y, function(t) {
return Math.pow(a + t * b, y);
};
}

export function hue(a, b) {
var d = b - a;
return d ? linear(a, d > 180 || d < -180 ? d - 360 * Math.round(d / 360) : d) : constant(isNaN(a) ? b : a);
}

export function gamma(y) {
return (y = +y) === 1 ? nogamma : function(a, b) {
return b - a ? exponential(a, b, y) : constant(isNaN(a) ? b : a);
};
}

export default function nogamma(a, b) {
var d = b - a;
return d ? linear(a, d) : constant(isNaN(a) ? b : a);
}
5 changes: 5 additions & 0 deletions src/constant.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export default function(x) {
return function() {
return x;
};
}
37 changes: 14 additions & 23 deletions src/cubehelix.js
Original file line number Diff line number Diff line change
@@ -1,33 +1,24 @@
import {cubehelix as color} from "d3-color";
import deltaHue from "./deltaHue";
import {cubehelix} from "d3-color";
import interpolateColor, {hue as interpolateHue} from "./color";

export default (function gamma(y) {
y = +y;

function cubehelix(a, b) {
a = color(a);
b = color(b);
var ah = a.h,
as = a.s,
al = a.l,
bh = b.h,
bs = b.s,
bl = b.l || 0;
if (isNaN(ah)) ah = bh;
if (isNaN(as)) as = bs;
if (isNaN(al)) al = bl;
bh = deltaHue(bh, ah) || 0;
bs = (bs - as) || 0;
bl -= al;
function interpolateCubehelix(start, end) {
var h = interpolateHue((start = cubehelix(start)).h, (end = cubehelix(end)).h),
s = interpolateColor(start.s, end.s),
l = interpolateColor(start.l, end.l),
opacity = interpolateColor(start.opacity, end.opacity);
return function(t) {
a.h = ah + bh * t;
a.s = as + bs * t;
a.l = al + bl * Math.pow(t, y);
return a + "";
start.h = h(t);
start.s = s(t);
start.l = l(Math.pow(t, y));
start.opacity = opacity(t);
return start + "";
};
}

cubehelix.gamma = gamma;
interpolateCubehelix.gamma = gamma;

return cubehelix;
return interpolateCubehelix;
})(1);
36 changes: 14 additions & 22 deletions src/cubehelixLong.js
Original file line number Diff line number Diff line change
@@ -1,32 +1,24 @@
import {cubehelix as color} from "d3-color";
import {cubehelix} from "d3-color";
import interpolateColor from "./color";

export default (function gamma(y) {
y = +y;

function cubehelix(a, b) {
a = color(a);
b = color(b);
var ah = a.h,
as = a.s,
al = a.l,
bh = b.h,
bs = b.s,
bl = b.l || 0;
if (isNaN(ah)) ah = bh;
if (isNaN(as)) as = bs;
if (isNaN(al)) al = bl;
bh = (bh - ah) || 0;
bs = (bs - as) || 0;
bl -= al;
function interpolateCubehelixLong(start, end) {
var h = interpolateColor((start = cubehelix(start)).h, (end = cubehelix(end)).h),
s = interpolateColor(start.s, end.s),
l = interpolateColor(start.l, end.l),
opacity = interpolateColor(start.opacity, end.opacity);
return function(t) {
a.h = ah + bh * t;
a.s = as + bs * t;
a.l = al + bl * Math.pow(t, y);
return a + "";
start.h = h(t);
start.s = s(t);
start.l = l(Math.pow(t, y));
start.opacity = opacity(t);
return start + "";
};
}

cubehelix.gamma = gamma;
interpolateCubehelixLong.gamma = gamma;

return cubehelix;
return interpolateCubehelixLong;
})(1);
6 changes: 0 additions & 6 deletions src/deltaHue.js

This file was deleted.

31 changes: 11 additions & 20 deletions src/hcl.js
Original file line number Diff line number Diff line change
@@ -1,25 +1,16 @@
import {hcl} from "d3-color";
import deltaHue from "./deltaHue";
import interpolateColor, {hue as interpolateHue} from "./color";

export default function(a, b) {
a = hcl(a);
b = hcl(b);
var ah = a.h,
ac = a.c,
al = a.l,
bh = b.h,
bc = b.c,
bl = b.l || 0;
if (isNaN(ah)) ah = bh;
if (isNaN(ac)) ac = bc;
if (isNaN(al)) al = bl;
bh = deltaHue(bh, ah) || 0;
bc = (bc - ac) || 0;
bl -= al;
export default function interpolateHcl(start, end) {
var h = interpolateHue((start = hcl(start)).h, (end = hcl(end)).h),
c = interpolateColor(start.c, end.c),
l = interpolateColor(start.l, end.l),
opacity = interpolateColor(start.opacity, end.opacity);
return function(t) {
a.h = ah + bh * t;
a.c = ac + bc * t;
a.l = al + bl * t;
return a + "";
start.h = h(t);
start.c = c(t);
start.l = l(t);
start.opacity = opacity(t);
return start + "";
};
}
30 changes: 11 additions & 19 deletions src/hclLong.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,16 @@
import {hcl} from "d3-color";
import interpolateColor from "./color";

export default function(a, b) {
a = hcl(a);
b = hcl(b);
var ah = a.h,
ac = a.c,
al = a.l,
bh = b.h,
bc = b.c,
bl = b.l || 0;
if (isNaN(ah)) ah = bh;
if (isNaN(ac)) ac = bc;
if (isNaN(al)) al = bl;
bh = (bh - ah) || 0;
bc = (bc - ac) || 0;
bl -= al;
export default function interpolateHclLong(start, end) {
var h = interpolateColor((start = hcl(start)).h, (end = hcl(end)).h),
c = interpolateColor(start.c, end.c),
l = interpolateColor(start.l, end.l),
opacity = interpolateColor(start.opacity, end.opacity);
return function(t) {
a.h = ah + bh * t;
a.c = ac + bc * t;
a.l = al + bl * t;
return a + "";
start.h = h(t);
start.c = c(t);
start.l = l(t);
start.opacity = opacity(t);
return start + "";
};
}
31 changes: 11 additions & 20 deletions src/hsl.js
Original file line number Diff line number Diff line change
@@ -1,25 +1,16 @@
import {hsl} from "d3-color";
import deltaHue from "./deltaHue";
import interpolateColor, {hue as interpolateHue} from "./color";

export default function(a, b) {
a = hsl(a);
b = hsl(b);
var ah = a.h,
as = a.s,
al = a.l,
bh = b.h,
bs = b.s,
bl = b.l || 0;
if (isNaN(ah)) ah = bh;
if (isNaN(as)) as = bs;
if (isNaN(al)) al = bl;
bh = deltaHue(bh, ah) || 0;
bs = (bs - as) || 0;
bl -= al;
export default function interpolateHsl(start, end) {
var h = interpolateHue((start = hsl(start)).h, (end = hsl(end)).h),
s = interpolateColor(start.s, end.s),
l = interpolateColor(start.l, end.l),
opacity = interpolateColor(start.opacity, end.opacity);
return function(t) {
a.h = ah + bh * t;
a.s = as + bs * t;
a.l = al + bl * t;
return a + "";
start.h = h(t);
start.s = s(t);
start.l = l(t);
start.opacity = opacity(t);
return start + "";
};
}
Loading

0 comments on commit e0f5fdf

Please sign in to comment.