# d3/d3

Color interpolators return strings.

```This partially reverts ce6526c. Although this
lacks the occasional convenience of a color instance, it has several advantages:
strings are immutable, so there is no concern of modifying the return value
(#1030); performance is improved; sometimes (e.g., Canvas, IE9 #1371) automatic
string coercion of values is unavailable, so strings are more convenient.```
1 parent 9be1fa2 commit 8c5558a6bad01dd58c22bd9f459dab83b81af41c mbostock committed Jul 19, 2013
 @@ -4927,10 +4927,7 @@ d3 = function() { b = d3.rgb(b); var ar = a.r, ag = a.g, ab = a.b, br = b.r - ar, bg = b.g - ag, bb = b.b - ab; return function(t) { - a.r = Math.round(ar + br * t); - a.g = Math.round(ag + bg * t); - a.b = Math.round(ab + bb * t); - return a; + return "#" + d3_rgb_hex(Math.round(ar + br * t)) + d3_rgb_hex(Math.round(ag + bg * t)) + d3_rgb_hex(Math.round(ab + bb * t)); }; } d3.interpolateObject = d3_interpolateObject; @@ -5155,10 +5152,7 @@ d3 = function() { if (isNaN(bc)) bc = 0, ac = isNaN(ac) ? b.c : ac; if (isNaN(bh)) bh = 0, ah = isNaN(ah) ? b.h : ah; else if (bh > 180) bh -= 360; else if (bh < -180) bh += 360; return function(t) { - a.h = ah + bh * t; - a.c = ac + bc * t; - a.l = al + bl * t; - return a; + return d3_hcl_lab(ah + bh * t, ac + bc * t, al + bl * t) + ""; }; } d3.interpolateHsl = d3_interpolateHsl; @@ -5169,10 +5163,7 @@ d3 = function() { if (isNaN(bs)) bs = 0, as = isNaN(as) ? b.s : as; if (isNaN(bh)) bh = 0, ah = isNaN(ah) ? b.h : ah; else if (bh > 180) bh -= 360; else if (bh < -180) bh += 360; return function(t) { - a.h = ah + bh * t; - a.s = as + bs * t; - a.l = al + bl * t; - return a; + return d3_hsl_rgb(ah + bh * t, as + bs * t, al + bl * t) + ""; }; } d3.interpolateLab = d3_interpolateLab; @@ -5181,10 +5172,7 @@ d3 = function() { b = d3.lab(b); var al = a.l, aa = a.a, ab = a.b, bl = b.l - al, ba = b.a - aa, bb = b.b - ab; return function(t) { - a.l = al + bl * t; - a.a = aa + ba * t; - a.b = ab + bb * t; - return a; + return d3_lab_rgb(al + bl * t, aa + ba * t, ab + bb * t) + ""; }; } d3.interpolateRound = d3_interpolateRound;
 @@ -15,9 +15,6 @@ function d3_interpolateHcl(a, b) { if (isNaN(bh)) bh = 0, ah = isNaN(ah) ? b.h : ah; else if (bh > 180) bh -= 360; else if (bh < -180) bh += 360; // shortest path return function(t) { - a.h = ah + bh * t; - a.c = ac + bc * t; - a.l = al + bl * t; - return a; + return d3_hcl_lab(ah + bh * t, ac + bc * t, al + bl * t) + ""; }; }
 @@ -15,9 +15,6 @@ function d3_interpolateHsl(a, b) { if (isNaN(bh)) bh = 0, ah = isNaN(ah) ? b.h : ah; else if (bh > 180) bh -= 360; else if (bh < -180) bh += 360; // shortest path return function(t) { - a.h = ah + bh * t; - a.s = as + bs * t; - a.l = al + bl * t; - return a; + return d3_hsl_rgb(ah + bh * t, as + bs * t, al + bl * t) + ""; }; }
 @@ -12,9 +12,6 @@ function d3_interpolateLab(a, b) { ba = b.a - aa, bb = b.b - ab; return function(t) { - a.l = al + bl * t; - a.a = aa + ba * t; - a.b = ab + bb * t; - return a; + return d3_lab_rgb(al + bl * t, aa + ba * t, ab + bb * t) + ""; }; }
 @@ -12,9 +12,9 @@ function d3_interpolateRgb(a, b) { bg = b.g - ag, bb = b.b - ab; return function(t) { - a.r = Math.round(ar + br * t); - a.g = Math.round(ag + bg * t); - a.b = Math.round(ab + bb * t); - return a; + return "#" + + d3_rgb_hex(Math.round(ar + br * t)) + + d3_rgb_hex(Math.round(ag + bg * t)) + + d3_rgb_hex(Math.round(ab + bb * t)); }; }
 @@ -8,38 +8,38 @@ suite.addBatch({ "interpolateHcl": { topic: load("interpolate/hcl"), // beware instanceof d3_Color "parses string input": function(d3) { - assert.hclEqual(d3.interpolateHcl("steelblue", "#f00")(.2), -69.78, 46.87, 52.62); - assert.hclEqual(d3.interpolateHcl("steelblue", "#f00")(.6), -14.89, 75.71, 52.93); + assert.strictEqual(d3.interpolateHcl("steelblue", "#f00")(.2), "#6978c9"); + assert.strictEqual(d3.interpolateHcl("steelblue", "#f00")(.6), "#e034a2"); }, "parses d3.hsl input": function(d3) { - assert.hclEqual(d3.interpolateHcl(d3.hsl("steelblue"), "#f00")(.2), -69.78, 46.87, 52.62); - assert.hclEqual(d3.interpolateHcl("steelblue", d3.hsl(0, 1, .5))(.6), -14.89, 75.71, 52.93); + assert.strictEqual(d3.interpolateHcl(d3.hsl("steelblue"), "#f00")(.2), "#6978c9"); + assert.strictEqual(d3.interpolateHcl("steelblue", d3.hsl(0, 1, .5))(.6), "#e034a2"); }, "parses d3.rgb input": function(d3) { - assert.hclEqual(d3.interpolateHcl(d3.rgb("steelblue"), "#f00")(.2), -69.78, 46.87, 52.62); - assert.hclEqual(d3.interpolateHcl("steelblue", d3.rgb(255, 0, 0))(.6), -14.89, 75.71, 52.93); + assert.strictEqual(d3.interpolateHcl(d3.rgb("steelblue"), "#f00")(.2), "#6978c9"); + assert.strictEqual(d3.interpolateHcl("steelblue", d3.rgb(255, 0, 0))(.6), "#e034a2"); }, "interpolates in HSL color space": function(d3) { - assert.hclEqual(d3.interpolateHcl("steelblue", "#f00")(.2), -69.78, 46.87, 52.62); + assert.strictEqual(d3.interpolateHcl("steelblue", "#f00")(.2), "#6978c9"); }, "uses source hue when destination hue is undefined": function(d3) { - assert.hclEqual(d3.interpolateHcl("#f60", "#000")(.5), 52.36, 90.07, 31.16); - assert.hclEqual(d3.interpolateHcl("#6f0", "#000")(.5), 131.26, 112.84, 44.54); + assert.equal(d3.interpolateHcl("#f60", "#000")(.5), "#9b0000"); + assert.equal(d3.interpolateHcl("#6f0", "#000")(.5), "#008100"); }, "uses destination hue when source hue is undefined": function(d3) { - assert.hclEqual(d3.interpolateHcl("#000", "#f60")(.5), 52.36, 90.07, 31.16); - assert.hclEqual(d3.interpolateHcl("#000", "#6f0")(.5), 131.26, 112.84, 44.54); + assert.equal(d3.interpolateHcl("#000", "#f60")(.5), "#9b0000"); + assert.equal(d3.interpolateHcl("#000", "#6f0")(.5), "#008100"); }, "uses source chroma when destination chroma is undefined": function(d3) { - assert.hclEqual(d3.interpolateHcl("#ccc", "#000")(.5), 158.20, 0.00, 41.02); - assert.hclEqual(d3.interpolateHcl("#f00", "#000")(.5), 40.00, 104.55, 26.62); + assert.equal(d3.interpolateHcl("#ccc", "#000")(.5), "#616161"); + assert.equal(d3.interpolateHcl("#f00", "#000")(.5), "#a60000"); }, "uses destination chroma when source chroma is undefined": function(d3) { - assert.hclEqual(d3.interpolateHcl("#000", "#ccc")(.5), 158.20, 0.00, 41.02); - assert.hclEqual(d3.interpolateHcl("#000", "#f00")(.5), 40.00, 104.55, 26.62); + assert.equal(d3.interpolateHcl("#000", "#ccc")(.5), "#616161"); + assert.equal(d3.interpolateHcl("#000", "#f00")(.5), "#a60000"); }, - "returns an instanceof d3.hcl": function(d3) { - assert.hclEqual(d3.interpolateHcl("steelblue", "#f00")(.2), -69.78, 46.87, 52.62); + "outputs a hexadecimal string": function(d3) { + assert.strictEqual(d3.interpolateHcl("steelblue", "#f00")(.2), "#6978c9"); } } });
 @@ -8,38 +8,38 @@ suite.addBatch({ "interpolateHsl": { topic: load("interpolate/hsl"), // beware instanceof d3_Color "parses string input": function(d3) { - assert.hslEqual(d3.interpolateHsl("steelblue", "#f00")(.2), 237.82, 0.5538, 0.4922); - assert.hslEqual(d3.interpolateHsl("steelblue", "#f00")(.6), 298.91, 0.7787, 0.4961); + assert.strictEqual(d3.interpolateHsl("steelblue", "#f00")(.2), "#383dc3"); + assert.strictEqual(d3.interpolateHsl("steelblue", "#f00")(.6), "#dd1ce1"); }, "parses d3.hsl input": function(d3) { - assert.hslEqual(d3.interpolateHsl(d3.hsl("steelblue"), "#f00")(.2), 237.82, 0.5538, 0.4922); - assert.hslEqual(d3.interpolateHsl("steelblue", d3.hsl(0, 1, .5))(.6), 298.91, 0.7787, 0.4961); + assert.strictEqual(d3.interpolateHsl(d3.hsl("steelblue"), "#f00")(.2), "#383dc3"); + assert.strictEqual(d3.interpolateHsl("steelblue", d3.hsl(0, 1, .5))(.6), "#dd1ce1"); }, "parses d3.rgb input": function(d3) { - assert.hslEqual(d3.interpolateHsl(d3.rgb("steelblue"), "#f00")(.2), 237.82, 0.5538, 0.4922); - assert.hslEqual(d3.interpolateHsl("steelblue", d3.rgb(255, 0, 0))(.6), 298.91, 0.7787, 0.4961); + assert.strictEqual(d3.interpolateHsl(d3.rgb("steelblue"), "#f00")(.2), "#383dc3"); + assert.strictEqual(d3.interpolateHsl("steelblue", d3.rgb(255, 0, 0))(.6), "#dd1ce1"); }, "interpolates in HSL color space": function(d3) { - assert.hslEqual(d3.interpolateHsl("steelblue", "#f00")(.2), 237.82, 0.5538, 0.4922); + assert.strictEqual(d3.interpolateHsl("steelblue", "#f00")(.2), "#383dc3"); }, "uses source hue when destination hue is undefined": function(d3) { - assert.hslEqual(d3.interpolateHsl("#f60", "#000")(.5), 24, 1, 0.2510); - assert.hslEqual(d3.interpolateHsl("#6f0", "#fff")(.5), 96, 1, 0.7510); + assert.equal(d3.interpolateHsl("#f60", "#000")(.5), "#803300"); + assert.equal(d3.interpolateHsl("#6f0", "#fff")(.5), "#b3ff80"); }, "uses destination hue when source hue is undefined": function(d3) { - assert.hslEqual(d3.interpolateHsl("#000", "#f60")(.5), 24, 1, 0.2510); - assert.hslEqual(d3.interpolateHsl("#fff", "#6f0")(.5), 96, 1, 0.7510); + assert.equal(d3.interpolateHsl("#000", "#f60")(.5), "#803300"); + assert.equal(d3.interpolateHsl("#fff", "#6f0")(.5), "#b3ff80"); }, "uses source saturation when destination saturation is undefined": function(d3) { - assert.hslEqual(d3.interpolateHsl("#ccc", "#000")(.5), NaN, 0, 0.4); - assert.hslEqual(d3.interpolateHsl("#f00", "#000")(.5), 0, 1, 0.2510); + assert.equal(d3.interpolateHsl("#ccc", "#000")(.5), "#666666"); + assert.equal(d3.interpolateHsl("#f00", "#000")(.5), "#800000"); }, "uses destination saturation when source saturation is undefined": function(d3) { - assert.hslEqual(d3.interpolateHsl("#000", "#ccc")(.5), NaN, 0, 0.4); - assert.hslEqual(d3.interpolateHsl("#000", "#f00")(.5), 0, 1, 0.2510); + assert.equal(d3.interpolateHsl("#000", "#ccc")(.5), "#666666"); + assert.equal(d3.interpolateHsl("#000", "#f00")(.5), "#800000"); }, - "returns an instanceof d3.hsl": function(d3) { - assert.hslEqual(d3.interpolateHsl("steelblue", "#f00")(.6), 298.91, 0.7787, 0.4961); + "outputs a hexadecimal string": function(d3) { + assert.strictEqual(d3.interpolateHsl("steelblue", "#f00")(.2), "#383dc3"); } } });
 @@ -20,44 +20,38 @@ suite.addBatch({ }, "when b is a color string": { - "interpolates RGB values": function(d3) { - assert.rgbEqual(d3.interpolate("#ff0000", "#008000")(.4), 153, 51, 0); + "interpolates RGB values and returns a hexadecimal string": function(d3) { + assert.strictEqual(d3.interpolate("#ff0000", "#008000")(.4), "#993300"); }, "interpolates named colors in RGB": function(d3) { - assert.rgbEqual(d3.interpolate("red", "green")(.4), 153, 51, 0); + assert.strictEqual(d3.interpolate("red", "green")(.4), "#993300"); }, "interpolates decimal RGB colors in RGB": function(d3) { - assert.rgbEqual(d3.interpolate("rgb(255,0,0)", "rgb(0,128,0)")(.4), 153, 51, 0); + assert.strictEqual(d3.interpolate("rgb(255,0,0)", "rgb(0,128,0)")(.4), "#993300"); }, "interpolates decimal HSL colors in RGB": function(d3) { - assert.rgbEqual(d3.interpolate("hsl(0,100%,50%)", "hsl(120,100%,25%)")(.4), 153, 51, 0); + assert.strictEqual(d3.interpolate("hsl(0,100%,50%)", "hsl(120,100%,25%)")(.4), "#993300"); }, "coerces a to a color": function(d3) { - assert.rgbEqual(d3.interpolate({toString: function() { return "red"; }}, "green")(.4), 153, 51, 0); - }, - "returns an instanceof d3.rgb": function(d3) { - assert.rgbEqual(d3.interpolate("steelblue", "#f00")(.2), 107, 104, 144); + assert.strictEqual(d3.interpolate({toString: function() { return "red"; }}, "green")(.4), "#993300"); } }, "when b is a color object": { "interpolates RGB values and returns a hexadecimal string": function(d3) { - assert.rgbEqual(d3.interpolate(d3.rgb(255, 0, 0), d3.rgb(0, 128, 0))(.4), 153, 51, 0); + assert.strictEqual(d3.interpolate(d3.rgb(255, 0, 0), d3.rgb(0, 128, 0))(.4), "#993300"); }, "interpolates d3.hsl in RGB": function(d3) { - assert.rgbEqual(d3.interpolate(d3.hsl("red"), d3.hsl("green"))(.4), 153, 51, 0); + assert.strictEqual(d3.interpolate(d3.hsl("red"), d3.hsl("green"))(.4), "#993300"); }, "interpolates d3.lab in RGB": function(d3) { - assert.rgbEqual(d3.interpolate(d3.lab("red"), d3.lab("green"))(.4), 153, 51, 0); + assert.strictEqual(d3.interpolate(d3.lab("red"), d3.lab("green"))(.4), "#993300"); }, "interpolates d3.hcl in RGB": function(d3) { - assert.rgbEqual(d3.interpolate(d3.hcl("red"), d3.hcl("green"))(.4), 153, 51, 0); + assert.strictEqual(d3.interpolate(d3.hcl("red"), d3.hcl("green"))(.4), "#993300"); }, "coerces a to a color": function(d3) { - assert.rgbEqual(d3.interpolate({toString: function() { return "red"; }}, "green")(.4), 153, 51, 0); - }, - "returns an instanceof d3.rgb": function(d3) { - assert.rgbEqual(d3.interpolate(d3.rgb("steelblue"), d3.rgb("#f00"))(.2), 107, 104, 144); + assert.strictEqual(d3.interpolate({toString: function() { return "red"; }}, "green")(.4), "#993300"); } },
 @@ -8,22 +8,22 @@ suite.addBatch({ "interpolateLab": { topic: load("interpolate/lab"), // beware instanceof d3_Color "parses string input": function(d3) { - assert.labEqual(d3.interpolateLab("steelblue", "#f00")(.2), 52.62, 12.76, -12.31); - assert.labEqual(d3.interpolateLab("steelblue", "#f00")(.6), 52.93, 46.42, 27.45); + assert.strictEqual(d3.interpolateLab("steelblue", "#f00")(.2), "#8a7793"); + assert.strictEqual(d3.interpolateLab("steelblue", "#f00")(.6), "#cf5952"); }, "parses d3.hsl input": function(d3) { - assert.labEqual(d3.interpolateLab(d3.hsl("steelblue"), "#f00")(.2), 52.62, 12.76, -12.31); - assert.labEqual(d3.interpolateLab("steelblue", d3.hsl(0, 1, .5))(.6), 52.93, 46.42, 27.45); + assert.strictEqual(d3.interpolateLab(d3.hsl("steelblue"), "#f00")(.2), "#8a7793"); + assert.strictEqual(d3.interpolateLab("steelblue", d3.hsl(0, 1, .5))(.6), "#cf5952"); }, "parses d3.rgb input": function(d3) { - assert.labEqual(d3.interpolateLab(d3.rgb("steelblue"), "#f00")(.2), 52.62, 12.76, -12.31); - assert.labEqual(d3.interpolateLab("steelblue", d3.rgb(255, 0, 0))(.6), 52.93, 46.42, 27.45); + assert.strictEqual(d3.interpolateLab(d3.rgb("steelblue"), "#f00")(.2), "#8a7793"); + assert.strictEqual(d3.interpolateLab("steelblue", d3.rgb(255, 0, 0))(.6), "#cf5952"); }, "interpolates in HSL color space": function(d3) { - assert.labEqual(d3.interpolateLab("steelblue", "#f00")(.2), 52.62, 12.76, -12.31); + assert.strictEqual(d3.interpolateLab("steelblue", "#f00")(.2), "#8a7793"); }, "returns an instanceof d3.lab": function(d3) { - assert.labEqual(d3.interpolateLab("steelblue", "#f00")(.2), 52.62, 12.76, -12.31); + assert.strictEqual(d3.interpolateLab("steelblue", "#f00")(.2), "#8a7793"); } } });
 @@ -16,10 +16,10 @@ suite.addBatch({ assert.deepEqual(interpolate(new a(2), new a(4))(.5), {a: 3, b: 12}); }, "interpolates color properties as rgb": function(interpolate) { - assert.deepEqual(interpolate({background: "red"}, {background: "green"})(.5), {background: d3.rgb(128, 64, 0)}); - assert.deepEqual(interpolate({fill: "red"}, {fill: "green"})(.5), {fill: d3.rgb(128, 64, 0)}); - assert.deepEqual(interpolate({stroke: "red"}, {stroke: "green"})(.5), {stroke: d3.rgb(128, 64, 0)}); - assert.deepEqual(interpolate({color: "red"}, {color: "green"})(.5), {color: d3.rgb(128, 64, 0)}); + assert.deepEqual(interpolate({background: "red"}, {background: "green"})(.5), {background: "#804000"}); + assert.deepEqual(interpolate({fill: "red"}, {fill: "green"})(.5), {fill: "#804000"}); + assert.deepEqual(interpolate({stroke: "red"}, {stroke: "green"})(.5), {stroke: "#804000"}); + assert.deepEqual(interpolate({color: "red"}, {color: "green"})(.5), {color: "#804000"}); }, "interpolates nested objects and arrays": function(interpolate) { assert.deepEqual(interpolate({foo: [2, 12]}, {foo: [4, 24]})(.5), {foo: [3, 18]});
 @@ -8,22 +8,22 @@ suite.addBatch({ "interpolateRgb": { topic: load("interpolate/rgb"), // beware instanceof d3_Color "parses string input": function(d3) { - assert.rgbEqual(d3.interpolateRgb("steelblue", "#f00")(.2), 107, 104, 144); - assert.rgbEqual(d3.interpolateRgb("steelblue", "#f00")(.6), 181, 52, 72); + assert.strictEqual(d3.interpolateRgb("steelblue", "#f00")(.2), "#6b6890"); + assert.strictEqual(d3.interpolateRgb("steelblue", "#f00")(.6), "#b53448"); }, "parses d3.rgb input": function(d3) { - assert.rgbEqual(d3.interpolateRgb(d3.rgb("steelblue"), "#f00")(.2), 107, 104, 144); - assert.rgbEqual(d3.interpolateRgb("steelblue", d3.rgb(255, 0, 0))(.6), 181, 52, 72); + assert.strictEqual(d3.interpolateRgb(d3.rgb("steelblue"), "#f00")(.2), "#6b6890"); + assert.strictEqual(d3.interpolateRgb("steelblue", d3.rgb(255, 0, 0))(.6), "#b53448"); }, "parses d3.hsl input": function(d3) { - assert.rgbEqual(d3.interpolateRgb(d3.hsl("steelblue"), "#f00")(.2), 107, 104, 144); - assert.rgbEqual(d3.interpolateRgb("steelblue", d3.hsl(0, 1, .5))(.6), 181, 52, 72); + assert.strictEqual(d3.interpolateRgb(d3.hsl("steelblue"), "#f00")(.2), "#6b6890"); + assert.strictEqual(d3.interpolateRgb("steelblue", d3.hsl(0, 1, .5))(.6), "#b53448"); }, "interpolates in RGB color space": function(d3) { - assert.rgbEqual(d3.interpolateRgb("steelblue", "#f00")(.2), 107, 104, 144); + assert.strictEqual(d3.interpolateRgb("steelblue", "#f00")(.2), "#6b6890"); }, - "returns an instanceof d3.rgb": function(d3) { - assert.rgbEqual(d3.interpolateRgb("steelblue", "#f00")(.2), 107, 104, 144); + "outputs an RGB string": function(d3) { + assert.strictEqual(d3.interpolateRgb("steelblue", "#f00")(.2), "#6b6890"); } } });
 @@ -80,21 +80,21 @@ suite.addBatch({ }, "can specify range values as arrays or objects": function(d3) { var x = d3.scale.linear().range([{color: "red"}, {color: "blue"}]); - assert.deepEqual(x(.5), {color: d3.rgb(128, 0, 128)}); + assert.deepEqual(x(.5), {color: "#800080"}); var x = d3.scale.linear().range([["red"], ["blue"]]); - assert.deepEqual(x(.5), [d3.rgb(128, 0, 128)]); + assert.deepEqual(x(.5), ["#800080"]); } }, "interpolate": { "defaults to d3.interpolate": function(d3) { var x = d3.scale.linear().range(["red", "blue"]); assert.equal(x.interpolate(), d3.interpolate); - assert.rgbEqual(x(.5), 128, 0, 128); + assert.equal(x(.5), "#800080"); }, "can specify a custom interpolator": function(d3) { var x = d3.scale.linear().range(["red", "blue"]).interpolate(d3.interpolateHsl); - assert.hslEqual(x(.5), -60, 1, .5); + assert.equal(x(.5), "#ff00ff"); } },
 @@ -79,21 +79,21 @@ suite.addBatch({ }, "can specify range values as arrays or objects": function(d3) { var x = d3.scale.log().range([{color: "red"}, {color: "blue"}]); - assert.deepEqual(x(5), {color: d3.rgb(77, 0, 178)}); + assert.deepEqual(x(5), {color: "#4d00b2"}); var x = d3.scale.log().range([["red"], ["blue"]]); - assert.deepEqual(x(5), [d3.rgb(77, 0, 178)]); + assert.deepEqual(x(5), ["#4d00b2"]); } }, "interpolate": { "defaults to d3.interpolate": function(d3) { var x = d3.scale.log().range(["red", "blue"]); assert.equal(x.interpolate(), d3.interpolate); - assert.rgbEqual(x(5), 77, 0, 178); + assert.equal(x(5), "#4d00b2"); }, "can specify a custom interpolator": function(d3) { var x = d3.scale.log().range(["red", "blue"]).interpolate(d3.interpolateHsl); - assert.hslEqual(x(5), -83.88, 1, .5); + assert.equal(x(5), "#9a00ff"); } },