Skip to content

Commit 811aa10

Browse files
committed
Scale interpolators & range rounding.
You can now override the scale interpolator by calling the `interpolate` method. One particularly useful interpolator is the new `d3.interpolateRound`, which is like `interpolateNumber`, except that it returns integers. This makes it easier to produce a scale that outputs exact pixel values, and avoid antialiasing artifacts. For convenience, the quantitative scales have a `rangeRound` method which sets the range and the interpolator at the same time. Similarly, a `rangeRoundBands` has been added to the ordinal scale.
1 parent 8036608 commit 811aa10

10 files changed

Lines changed: 159 additions & 118 deletions

File tree

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
JS_COMPILER = \
22
java -jar lib/google-compiler/compiler.jar \
33
--externs=src/externs.js \
4-
--warning_level=VERBOSE \
54
--charset=UTF-8
65

76
all: \
@@ -31,6 +30,7 @@ d3.core.js: \
3130
src/core/object.js \
3231
src/core/array.js \
3332
src/core/functor.js \
33+
src/core/rebind.js \
3434
src/core/ascending.js \
3535
src/core/descending.js \
3636
src/core/min.js \

d3.js

Lines changed: 48 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
(function(){d3 = {version: "0.29.4"}; // semver
1+
(function(){d3 = {version: "0.29.5"}; // semver
22
if (!Date.now) Date.now = function() {
33
return +new Date();
44
};
@@ -13,6 +13,13 @@ function d3_array(psuedoarray) {
1313
function d3_functor(v) {
1414
return typeof v == "function" ? v : function() { return v; };
1515
}
16+
// A getter-setter method that preserves the appropriate `this` context.
17+
function d3_rebind(object, method) {
18+
return function() {
19+
var x = method.apply(object, arguments);
20+
return arguments.length ? object : x;
21+
};
22+
}
1623
d3.ascending = function(a, b) {
1724
return a < b ? -1 : a > b ? 1 : 0;
1825
};
@@ -462,6 +469,11 @@ d3.interpolateNumber = function(a, b) {
462469
return function(t) { return a + b * t; };
463470
};
464471

472+
d3.interpolateRound = function(a, b) {
473+
b -= a;
474+
return function(t) { return Math.round(a + b * t); };
475+
};
476+
465477
d3.interpolateString = function(a, b) {
466478
var m, // current match
467479
i, // current index
@@ -1752,7 +1764,8 @@ d3.scale.linear = function() {
17521764
y1 = 1,
17531765
kx = 1 / (x1 - x0),
17541766
ky = (x1 - x0) / (y1 - y0),
1755-
i = d3.interpolate(y0, y1);
1767+
interpolate = d3.interpolate,
1768+
i = interpolate(y0, y1);
17561769

17571770
function scale(x) {
17581771
return i((x - x0) * kx);
@@ -1762,7 +1775,6 @@ d3.scale.linear = function() {
17621775
return (y - y0) * ky + x0; // TODO assumes number?
17631776
};
17641777

1765-
/** @param {*=} x */
17661778
scale.domain = function(x) {
17671779
if (!arguments.length) return [x0, x1];
17681780
x0 = x[0];
@@ -1772,13 +1784,22 @@ d3.scale.linear = function() {
17721784
return scale;
17731785
};
17741786

1775-
/** @param {*=} x */
17761787
scale.range = function(x) {
17771788
if (!arguments.length) return [y0, y1];
17781789
y0 = x[0];
17791790
y1 = x[1];
17801791
ky = (x1 - x0) / (y1 - y0);
1781-
i = d3.interpolate(y0, y1); // TODO allow override?
1792+
i = interpolate(y0, y1);
1793+
return scale;
1794+
};
1795+
1796+
scale.rangeRound = function(x) {
1797+
return scale.range(x).interpolate(d3.interpolateRound);
1798+
};
1799+
1800+
scale.interpolate = function(x) {
1801+
if (!arguments.length) return interpolate;
1802+
i = (interpolate = x)(y0, y1);
17821803
return scale;
17831804
};
17841805

@@ -1834,17 +1855,15 @@ d3.scale.log = function() {
18341855
return pow(linear.invert(x));
18351856
};
18361857

1837-
/** @param {*=} x */
18381858
scale.domain = function(x) {
18391859
if (!arguments.length) return linear.domain().map(pow);
18401860
linear.domain(x.map(log));
18411861
return scale;
18421862
};
18431863

1844-
scale.range = function() {
1845-
var x = linear.range.apply(linear, arguments);
1846-
return arguments.length ? scale : x;
1847-
};
1864+
scale.range = d3_rebind(scale, linear.range);
1865+
scale.rangeRound = d3_rebind(scale, linear.rangeRound);
1866+
scale.interpolate = d3_rebind(scale, linear.interpolate);
18481867

18491868
scale.ticks = function() {
18501869
var d = linear.domain(),
@@ -1866,6 +1885,7 @@ d3.scale.log = function() {
18661885
};
18671886
d3.scale.pow = function() {
18681887
var linear = d3.scale.linear(),
1888+
tick = d3.scale.linear(), // TODO better tick formatting...
18691889
p = 1,
18701890
b = 1 / p;
18711891

@@ -1881,34 +1901,22 @@ d3.scale.pow = function() {
18811901
return linear(powp(x));
18821902
}
18831903

1884-
function tick() {
1885-
return d3.scale.linear().domain(scale.domain());
1886-
}
1887-
18881904
scale.invert = function(x) {
18891905
return powb(linear.invert(x));
18901906
};
18911907

1892-
/** @param {*=} x */
18931908
scale.domain = function(x) {
18941909
if (!arguments.length) return linear.domain().map(powb);
18951910
linear.domain(x.map(powp));
1911+
tick.domain(x);
18961912
return scale;
18971913
};
18981914

1899-
scale.range = function() {
1900-
var x = linear.range.apply(linear, arguments);
1901-
return arguments.length ? scale : x;
1902-
};
1903-
1904-
// TODO better tick formatting...
1905-
scale.ticks = function(m) {
1906-
return tick().ticks(m);
1907-
};
1908-
1909-
scale.tickFormat = function(m) {
1910-
return tick().tickFormat(m);
1911-
};
1915+
scale.range = d3_rebind(scale, linear.range);
1916+
scale.rangeRound = d3_rebind(scale, linear.rangeRound);
1917+
scale.inteprolate = d3_rebind(scale, linear.interpolate);
1918+
scale.ticks = tick.ticks;
1919+
scale.tickFormat = tick.tickFormat;
19121920

19131921
scale.exponent = function(x) {
19141922
if (!arguments.length) return p;
@@ -1973,6 +1981,18 @@ d3.scale.ordinal = function() {
19731981
return scale;
19741982
};
19751983

1984+
scale.rangeRoundBands = function(x, padding) {
1985+
if (arguments.length < 2) padding = 0;
1986+
var start = x[0],
1987+
stop = x[1],
1988+
diff = stop - start,
1989+
step = Math.floor(diff / (domain.length + padding)),
1990+
err = diff - (domain.length - padding) * step;
1991+
range = d3.range(start + Math.round(err / 2), stop, step);
1992+
rangeBand = Math.round(step * (1 - padding));
1993+
return scale;
1994+
};
1995+
19761996
scale.rangeBand = function() {
19771997
return rangeBand;
19781998
};

0 commit comments

Comments
 (0)