Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -573,6 +573,10 @@ See [*continuous*.clamp](#continuous_clamp).

If *interpolator* is specified, sets the scale’s interpolator to the specified function. If *interpolator* is not specified, returns the scale’s current interpolator.

<a name="sequential_invert" href="#sequential_invert">#</a> <i>sequential</i>.<b>invert</b>(<i>fraction</i>) · [Source](https://github.com/d3/d3-scale/blob/master/src/sequential.js)

Inverts the given interpolation *fraction* and returns the corresponding domain value. This method does not invert the output of the interpolator function (which may be non-invertible), but rather inverts fractional values that serve as input to the interpolator.

<a name="sequential_range" href="#sequential_range">#</a> <i>sequential</i>.<b>range</b>([<i>range</i>]) · [Source](https://github.com/d3/d3-scale/blob/master/src/sequential.js), [Examples](https://observablehq.com/@d3/sequential-scales)

See [*continuous*.range](#continuous_range). If *range* is specified, implicitly uses [d3.interpolate](https://github.com/d3/d3-interpolate/blob/master/README.md#interpolate) as the interpolator.
Expand Down Expand Up @@ -637,6 +641,10 @@ See [*continuous*.clamp](#continuous_clamp).

If *interpolator* is specified, sets the scale’s interpolator to the specified function. If *interpolator* is not specified, returns the scale’s current interpolator.

<a name="diverging_invert" href="#diverging_invert">#</a> <i>diverging</i>.<b>invert</b>(<i>fraction</i>) · [Source](https://github.com/d3/d3-scale/blob/master/src/diverging.js)

Inverts the given interpolation *fraction* and returns the corresponding domain value. This method does not invert the output of the interpolator function (which may be non-invertible), but rather inverts fractional values that serve as input to the interpolator.

<a name="diverging_range" href="#diverging_range">#</a> <i>diverging</i>.<b>range</b>([<i>range</i>]) · [Source](https://github.com/d3/d3-scale/blob/master/src/diverging.js), [Examples](https://observablehq.com/@d3/diverging-scales)

See [*continuous*.range](#continuous_range). If *range* is specified, implicitly uses [d3.interpolate](https://github.com/d3/d3-interpolate/blob/master/README.md#interpolate) as the interpolator.
Expand Down
13 changes: 10 additions & 3 deletions src/diverging.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,20 @@ function transformer() {
k21,
interpolator = identity,
transform,
untransform,
clamp = false,
unknown;

function scale(x) {
return isNaN(x = +x) ? unknown : (x = 0.5 + ((x = +transform(x)) - t1) * (s * x < s * t1 ? k10 : k21), interpolator(clamp ? Math.max(0, Math.min(1, x)) : x));
}

scale.invert = function(_) {
_ = clamp ? Math.max(0, Math.min(1, _)) : _;
return _ === 0 ? x0 : _ === 1 ? x2 : _ === 0.5 ? x1
: untransform((_ - 0.5) / (_ < 0.5 ? k10 : k21) + t1);
};

scale.domain = function(_) {
return arguments.length ? ([x0, x1, x2] = _, t0 = transform(x0 = +x0), t1 = transform(x1 = +x1), t2 = transform(x2 = +x2), k10 = t0 === t1 ? 0 : 0.5 / (t1 - t0), k21 = t1 === t2 ? 0 : 0.5 / (t2 - t1), s = t1 < t0 ? -1 : 1, scale) : [x0, x1, x2];
};
Expand Down Expand Up @@ -53,14 +60,14 @@ function transformer() {
return arguments.length ? (unknown = _, scale) : unknown;
};

return function(t) {
transform = t, t0 = t(x0), t1 = t(x1), t2 = t(x2), k10 = t0 === t1 ? 0 : 0.5 / (t1 - t0), k21 = t1 === t2 ? 0 : 0.5 / (t2 - t1), s = t1 < t0 ? -1 : 1;
return function(t, u) {
transform = t, t0 = t(x0), t1 = t(x1), t2 = t(x2), k10 = t0 === t1 ? 0 : 0.5 / (t1 - t0), k21 = t1 === t2 ? 0 : 0.5 / (t2 - t1), s = t1 < t0 ? -1 : 1, untransform = u;
return scale;
};
}

export default function diverging() {
var scale = linearish(transformer()(identity));
var scale = linearish(transformer()(identity, identity));

scale.copy = function() {
return copy(scale, diverging());
Expand Down
12 changes: 9 additions & 3 deletions src/sequential.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ function transformer() {
t1,
k10,
transform,
untransform,
interpolator = identity,
clamp = false,
unknown;
Expand All @@ -21,6 +22,11 @@ function transformer() {
return isNaN(x = +x) ? unknown : interpolator(k10 === 0 ? 0.5 : (x = (transform(x) - t0) * k10, clamp ? Math.max(0, Math.min(1, x)) : x));
}

scale.invert = function(_) {
_ = clamp ? Math.max(0, Math.min(1, _)) : _;
return _ === 0 ? x0 : _ === 1 ? x1 : untransform(_ / k10 + t0);
};

scale.domain = function(_) {
return arguments.length ? ([x0, x1] = _, t0 = transform(x0 = +x0), t1 = transform(x1 = +x1), k10 = t0 === t1 ? 0 : 1 / (t1 - t0), scale) : [x0, x1];
};
Expand Down Expand Up @@ -48,8 +54,8 @@ function transformer() {
return arguments.length ? (unknown = _, scale) : unknown;
};

return function(t) {
transform = t, t0 = t(x0), t1 = t(x1), k10 = t0 === t1 ? 0 : 1 / (t1 - t0);
return function(t, u) {
transform = t, t0 = t(x0), t1 = t(x1), k10 = t0 === t1 ? 0 : 1 / (t1 - t0), untransform = u;
return scale;
};
}
Expand All @@ -63,7 +69,7 @@ export function copy(source, target) {
}

export default function sequential() {
var scale = linearish(transformer()(identity));
var scale = linearish(transformer()(identity, identity));

scale.copy = function() {
return copy(scale, sequential());
Expand Down
25 changes: 25 additions & 0 deletions test/diverging-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -162,3 +162,28 @@ tape("scaleDiverging(range) sets the interpolator", function(test) {
test.deepEqual(s.range(), [1, 3, 10]);
test.end();
});

tape("scaleDiverging.invert(value) inverts interpolation fractions", function(test) {
var s = scale.scaleDiverging().domain([1,2,4]);
test.equal(s.invert(0), 1);
test.equal(s.invert(0.25), 1.5);
test.equal(s.invert(0.50), 2);
test.equal(s.invert(0.75), 3);
test.equal(s.invert(1), 4);
test.equal(s.invert(-0.5), 0);
test.equal(s.invert(1.5), 6);
test.end();
});

tape("scaleDivergingLog.invert(value) inverts interpolation fractions", function(test) {
var d = [1, 20, 100];
var s = scale.scaleDivergingLog().domain(d);
test.equal(s.invert(0), d[0]);
test.equal(s.invert(0.25), Math.exp(Math.log(d[0]) + 0.5 * (Math.log(d[1]) - Math.log(d[0]))));
test.equal(s.invert(0.50), d[1]);
test.equal(s.invert(0.75), Math.exp(Math.log(d[1]) + 0.5 * (Math.log(d[2]) - Math.log(d[1]))));
test.equal(s.invert(1), d[2]);
test.inDelta(s.invert(-0.5), Math.exp(Math.log(d[0]) - 1 * (Math.log(d[1]) - Math.log(d[0]))));
test.inDelta(s.invert(1.5), Math.exp(Math.log(d[1]) + 2 * (Math.log(d[2]) - Math.log(d[1]))));
test.end();
});
25 changes: 25 additions & 0 deletions test/sequential-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -131,3 +131,28 @@ tape("scaleSequential(range) sets the interpolator", function(test) {
test.deepEqual(s.range(), [1, 3]);
test.end();
});

tape("scaleSequential.invert(value) inverts interpolation fractions", function(test) {
var s = scale.scaleSequential().domain([1,5]);
test.equal(s.invert(0), 1);
test.equal(s.invert(0.25), 2);
test.equal(s.invert(0.50), 3);
test.equal(s.invert(0.75), 4);
test.equal(s.invert(1), 5);
test.equal(s.invert(-1), -3);
test.equal(s.invert(2), 9);
test.end();
});

tape("scaleSequentialLog.invert(value) inverts interpolation fractions", function(test) {
var d = [1, 100];
var s = scale.scaleSequentialLog().domain(d);
test.equal(s.invert(0), d[0]);
test.equal(s.invert(0.25), Math.exp(Math.log(d[0]) + 0.25 * (Math.log(d[1]) - Math.log(d[0]))));
test.equal(s.invert(0.50), Math.exp(Math.log(d[0]) + 0.50 * (Math.log(d[1]) - Math.log(d[0]))));
test.equal(s.invert(0.75), Math.exp(Math.log(d[0]) + 0.75 * (Math.log(d[1]) - Math.log(d[0]))));
test.equal(s.invert(1), d[1]);
test.inDelta(s.invert(-1), d[0] / d[1]);
test.inDelta(s.invert(2), d[1] * d[1]);
test.end();
});