-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Includes d3.interpolateLab and d3.interpolateHcl.
- Loading branch information
Showing
10 changed files
with
434 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
d3.hcl = function(h, c, l) { | ||
return arguments.length === 1 | ||
? (h instanceof d3_Hcl ? d3_hcl(h.h, h.c, h.l) | ||
: (h instanceof d3_Lab ? d3_lab_hcl(h.l, h.a, h.b) | ||
: d3_lab_hcl((h = d3_rgb_lab((h = d3.rgb(h)).r, h.g, h.b)).l, h.a, h.b))) | ||
: d3_hcl(+h, +c, +l); | ||
}; | ||
|
||
function d3_hcl(h, c, l) { | ||
return new d3_Hcl(h, c, l); | ||
} | ||
|
||
function d3_Hcl(h, c, l) { | ||
this.h = h; | ||
this.c = c; | ||
this.l = l; | ||
} | ||
|
||
d3_Hcl.prototype.brighter = function(k) { | ||
return d3_hcl(this.h, this.c, Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1))); | ||
}; | ||
|
||
d3_Hcl.prototype.darker = function(k) { | ||
return d3_hcl(this.h, this.c, Math.max(0, this.l - d3_lab_K * (arguments.length ? k : 1))); | ||
}; | ||
|
||
d3_Hcl.prototype.rgb = function() { | ||
return d3_hcl_lab(this.h, this.c, this.l).rgb(); | ||
}; | ||
|
||
d3_Hcl.prototype.toString = function() { | ||
return this.rgb() + ""; | ||
}; | ||
|
||
function d3_hcl_lab(h, c, l) { | ||
return d3_lab(l, Math.cos(h *= Math.PI / 180) * c, Math.sin(h) * c); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
d3.lab = function(l, a, b) { | ||
return arguments.length === 1 | ||
? (l instanceof d3_Lab ? d3_lab(l.l, l.a, l.b) | ||
: (l instanceof d3_Hcl ? d3_hcl_lab(l.l, l.c, l.h) | ||
: d3_rgb_lab((l = d3.rgb(l)).r, l.g, l.b))) | ||
: d3_lab(+l, +a, +b); | ||
}; | ||
|
||
function d3_lab(l, a, b) { | ||
return new d3_Lab(l, a, b); | ||
} | ||
|
||
function d3_Lab(l, a, b) { | ||
this.l = l; | ||
this.a = a; | ||
this.b = b; | ||
} | ||
|
||
// Corresponds roughly to RGB brighter/darker | ||
var d3_lab_K = 18; | ||
|
||
// D65 standard referent | ||
var d3_lab_X = 0.950470, | ||
d3_lab_Y = 1, | ||
d3_lab_Z = 1.088830; | ||
|
||
d3_Lab.prototype.brighter = function(k) { | ||
return d3_lab(Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1)), this.a, this.b); | ||
}; | ||
|
||
d3_Lab.prototype.darker = function(k) { | ||
return d3_lab(Math.max(0, this.l - d3_lab_K * (arguments.length ? k : 1)), this.a, this.b); | ||
}; | ||
|
||
d3_Lab.prototype.rgb = function() { | ||
return d3_lab_rgb(this.l, this.a, this.b); | ||
}; | ||
|
||
d3_Lab.prototype.toString = function() { | ||
return this.rgb() + ""; | ||
}; | ||
|
||
function d3_lab_rgb(l, a, b) { | ||
var y = (l + 16) / 116, | ||
x = y + a / 500, | ||
z = y - b / 200; | ||
x = d3_lab_xyz(x) * d3_lab_X; | ||
y = d3_lab_xyz(y) * d3_lab_Y; | ||
z = d3_lab_xyz(z) * d3_lab_Z; | ||
return d3_rgb( | ||
d3_xyz_rgb( 3.2404542 * x - 1.5371385 * y - 0.4985314 * z), | ||
d3_xyz_rgb(-0.9692660 * x + 1.8760108 * y + 0.0415560 * z), | ||
d3_xyz_rgb( 0.0556434 * x - 0.2040259 * y + 1.0572252 * z) | ||
); | ||
} | ||
|
||
function d3_lab_hcl(l, a, b) { | ||
return d3_hcl(Math.atan2(b, a) / Math.PI * 180, Math.sqrt(a * a + b * b), l); | ||
} | ||
|
||
function d3_lab_xyz(x) { | ||
return x > 0.206893034 ? x * x * x : (x - 4 / 29) / 7.787037; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
function d3_xyz_lab(x) { | ||
return x > 0.008856 ? Math.pow(x, 1 / 3) : 7.787037 * x + 4 / 29; | ||
} | ||
|
||
function d3_xyz_rgb(r) { | ||
return Math.round(255 * (r <= 0.00304 ? 12.92 * r : 1.055 * Math.pow(r, 1 / 2.4) - 0.055)); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
require("../env"); | ||
|
||
var vows = require("vows"), | ||
assert = require("assert"); | ||
|
||
var suite = vows.describe("d3.hcl"); | ||
|
||
suite.addBatch({ | ||
"hcl": { | ||
topic: function() { | ||
return d3.hcl; | ||
}, | ||
"converts string channel values to numbers": function(hcl) { | ||
assertHclEqual(hcl("50", "-4", "32"), 50, -4, 32); | ||
}, | ||
"converts null channel values to zero": function(hcl) { | ||
assertHclEqual(hcl(null, null, null), 0, 0, 0); | ||
}, | ||
"exposes h, c and l properties": function(hcl) { | ||
var color = hcl(50, -4, 32); | ||
assert.equal(color.h, 50); | ||
assert.equal(color.c, -4); | ||
assert.equal(color.l, 32); | ||
}, | ||
"changing h, c or l affects the string format": function(hcl) { | ||
var color = hcl(50, -4, 32); | ||
assert.equal(color + "", "#444d50"); | ||
color.h++; | ||
assert.equal(color + "", "#444d50"); | ||
color.c++; | ||
assert.equal(color + "", "#464c4f"); | ||
color.l++; | ||
assert.equal(color + "", "#494f51"); | ||
}, | ||
"parses hexadecimal shorthand format (e.g., \"#abc\")": function(hcl) { | ||
assertHclEqual(hcl("#abc"), -102.28223831811077, 10.774886733325554, 75.10497524893663); | ||
}, | ||
"parses hexadecimal format (e.g., \"#abcdef\")": function(hcl) { | ||
assertHclEqual(hcl("#abcdef"), -100.15785184209284, 20.768234621934273, 81.04386565274363); | ||
}, | ||
"parses HSL format (e.g., \"hsl(210, 64%, 13%)\")": function(hcl) { | ||
assertHclEqual(hcl("hsl(210, 64.7058%, 13.33333%)"), -89.58282792342067, 16.833655998102003, 12.65624852526134); | ||
}, | ||
"parses color names (e.g., \"moccasin\")": function(hcl) { | ||
assertHclEqual(hcl("moccasin"), 84.71288921124494, 26.472460854104156, 91.72317744746022); | ||
}, | ||
"parses and converts RGB format (e.g., \"rgb(102, 102, 0)\")": function(hcl) { | ||
assertHclEqual(hcl("rgb(102, 102, 0)"), 102.85124420310271, 49.44871600399321, 41.73251953866431); | ||
}, | ||
"can convert from RGB": function(hcl) { | ||
assertHclEqual(hcl(d3.rgb(12, 34, 56)), -89.58282792342067, 16.833655998102003, 12.65624852526134); | ||
}, | ||
"can convert from HSL": function(hcl) { | ||
assertHclEqual(hcl(d3.hcl(20, .8, .3)), 20, 0.8, 0.3); | ||
}, | ||
"can convert to RGB": function(hcl) { | ||
assert.rgbEqual(hcl("steelblue").rgb(), 70, 130, 180); | ||
}, | ||
"can derive a brighter color": function(hcl) { | ||
assertHclEqual(hcl("steelblue").brighter(), -97.21873224090723, 32.44906314974561, 70.46551718768575); | ||
assertHclEqual(hcl("steelblue").brighter(.5), -97.21873224090723, 32.44906314974561, 61.46551718768575); | ||
}, | ||
"can derive a darker color": function(hcl) { | ||
assertHclEqual(hcl("lightsteelblue").darker(), -94.8160116310511, 15.26488988314746, 60.45157936968134); | ||
assertHclEqual(hcl("lightsteelblue").darker(.5), -94.8160116310511, 15.26488988314746, 69.45157936968134); | ||
}, | ||
"string coercion returns RGB format": function(hcl) { | ||
assert.strictEqual(hcl("hsl(60, 100%, 20%)") + "", "#666600"); | ||
assert.strictEqual(hcl(d3.hcl(60, -4, 32)) + "", "#454c51"); | ||
}, | ||
"roundtrip to HSL is idempotent": function(hcl) { | ||
assert.hslEqual(d3.hsl(hcl("steelblue")), d3.hsl("steelblue")); | ||
}, | ||
"roundtrip to RGB is idempotent": function(hcl) { | ||
assert.hslEqual(d3.rgb(hcl("steelblue")), d3.rgb("steelblue")); | ||
}, | ||
"roundtrip to Lab is idempotent": function(hcl) { | ||
assert.hslEqual(d3.lab(hcl("steelblue")), d3.lab("steelblue")); | ||
} | ||
} | ||
}); | ||
|
||
suite.export(module); | ||
|
||
function assertHclEqual(actual, h, c, l, message) { | ||
if (Math.abs(actual.h - h) > 1e-6 || Math.abs(actual.c - c) > 1e-6 || Math.abs(actual.l - l) > 1e-6) { | ||
assert.fail("hcl(" + actual.h + ", " + actual.c + ", " + actual.l + ")", "hcl(" + h + ", " + c + ", " + l + ")", message || "expected {expected}, got {actual}", null, assertHclEqual); | ||
} | ||
} |
Oops, something went wrong.