Skip to content

Commit

Permalink
feat: added throw error for testing missing parameters (#90)
Browse files Browse the repository at this point in the history
feat: added throw errors for missing parameters in generateContrastColors
test: corrected what binarySearch value should be returned in test
test: added additional binary search test to ensure correct index of original list returns correct value
chore: fix code style
  • Loading branch information
NateBaldwinDesign authored and lazd committed Dec 6, 2019
1 parent ddaee9f commit 2f5dff7
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 25 deletions.
54 changes: 32 additions & 22 deletions packages/contrast-colors/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ import * as d3hsv from 'd3-hsv';
Object.assign(d3, d3hsluv, d3hsv, d3cam02);

function cArray(c) {
var L = d3.hsluv(c).l;
var U = d3.hsluv(c).u;
var V = d3.hsluv(c).v;
let L = d3.hsluv(c).l;
let U = d3.hsluv(c).u;
let V = d3.hsluv(c).v;

return new Array(L, U, V);
}
Expand All @@ -31,15 +31,15 @@ function createScale({
shift = 1,
fullScale = true
} = {}) {
var domains = colorKeys
let domains = colorKeys
.map(key => swatches - swatches * (d3.hsluv(key).v / 100))
.sort((a, b) => a - b)
.concat(swatches);

domains.unshift(0);

// Test logarithmic domain (for non-contrast-based scales)
var sqrtDomains = d3.scalePow()
let sqrtDomains = d3.scalePow()
.exponent(shift)
.domain([1, swatches])
.range([1, swatches]);
Expand All @@ -54,15 +54,15 @@ function createScale({
// Transform square root in order to smooth gradient
domains = sqrtDomains;

var sortedColor = colorKeys
let sortedColor = colorKeys
// Convert to HSLuv and keep track of original indices
.map((c, i) => { return { colorKeys: cArray(c), index: i } })
// Sort by lightness
.sort((c1, c2) => c2.colorKeys[2] - c1.colorKeys[2])
// Retrieve original RGB color
.map(data => colorKeys[data.index]);

var inverseSortedColor = colorKeys
let inverseSortedColor = colorKeys
// Convert to HSLuv and keep track of original indices
.map((c, i) => { return {colorKeys: cArray(c), index: i} })
// Sort by lightness
Expand Down Expand Up @@ -160,10 +160,10 @@ function createScale({
.interpolate(d3.interpolateHsv);
}
else {
throw new Error(`Colorspace ${colorspace} not supported`)
throw new Error(`Colorspace ${colorspace} not supported`);
}

var Colors = d3.range(swatches).map(d => scale(d));
let Colors = d3.range(swatches).map(d => scale(d));

let colors = Colors.filter(el => el != null);

Expand All @@ -189,36 +189,46 @@ function generateContrastColors({
ratios,
colorspace = 'LAB'
} = {}) {
if (!base) {
throw new Error(`Base is undefined`);
}
if (!colorKeys) {
throw new Error(`Color Keys are undefined`);
}
if (!ratios) {
throw new Error(`Ratios are undefined`);
}

let swatches = 3000;

let scaleData = createScale({swatches: swatches, colorKeys: colorKeys, colorspace: colorspace, shift: 1});

var Contrasts = d3.range(swatches).map((d) => {
var rgbArray = [d3.rgb(scaleData.scale(d)).r, d3.rgb(scaleData.scale(d)).g, d3.rgb(scaleData.scale(d)).b];
var baseRgbArray = [d3.rgb(base).r, d3.rgb(base).g, d3.rgb(base).b];
var ca = contrast(rgbArray, baseRgbArray).toFixed(2);
let Contrasts = d3.range(swatches).map((d) => {
let rgbArray = [d3.rgb(scaleData.scale(d)).r, d3.rgb(scaleData.scale(d)).g, d3.rgb(scaleData.scale(d)).b];
let baseRgbArray = [d3.rgb(base).r, d3.rgb(base).g, d3.rgb(base).b];
let ca = contrast(rgbArray, baseRgbArray).toFixed(2);

return Number(ca);
});

let contrasts = Contrasts.filter(el => el != null);

var baseLum = luminance(d3.rgb(base).r, d3.rgb(base).g, d3.rgb(base).b);
let baseLum = luminance(d3.rgb(base).r, d3.rgb(base).g, d3.rgb(base).b);

let newColors = [];
ratios = ratios.map(Number);

// Return color matching target ratio, or closest number
for (let i=0; i < ratios.length; i++){
var r = binarySearch(contrasts, ratios[i], baseLum);
let r = binarySearch(contrasts, ratios[i], baseLum);
newColors.push(d3.rgb(scaleData.colors[r]).hex());
}

return newColors;
}

function luminance(r, g, b) {
var a = [r, g, b].map((v) => {
let a = [r, g, b].map((v) => {
v /= 255;
return v <= 0.03928
? v / 12.92
Expand All @@ -233,11 +243,11 @@ function luminance(r, g, b) {

// Separate files in a lib folder as well.
function contrast(color, base) {
var colorLum = luminance(color[0], color[1], color[2]);
var baseLum = luminance(base[0], base[1], base[2]);
let colorLum = luminance(color[0], color[1], color[2]);
let baseLum = luminance(base[0], base[1], base[2]);

var cr1 = (colorLum + 0.05) / (baseLum + 0.05);
var cr2 = (baseLum + 0.05) / (colorLum + 0.05);
let cr1 = (colorLum + 0.05) / (baseLum + 0.05);
let cr2 = (baseLum + 0.05) / (colorLum + 0.05);

if (baseLum < 0.5) {
if (cr1 >= 1) {
Expand Down Expand Up @@ -265,8 +275,8 @@ function binarySearch(list, value, baseLum) {
let stop = list.length - 1
let middle = Math.floor((start + stop) / 2)

var minContrast = Math.min(...list);
var maxContrast = Math.max(...list);
let minContrast = Math.min(...list);
let maxContrast = Math.max(...list);

// While the middle is not what we're looking for and the list does not have a single item
while (list[middle] !== value && start < stop) {
Expand Down
45 changes: 42 additions & 3 deletions packages/contrast-colors/test/binarySearch.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,48 @@ governing permissions and limitations under the License.
import test from 'ava';
import { binarySearch } from '../index.js';

test('should return index of exact match (ascending)', function(t) {
let list = [1, 2, 3, 3.07, 3.1, 3.12, 3.13, 3.14, 3.3, 5, 12];
let value = 3.12;
let baseLum = 0.7;
let searchIndex = binarySearch(list, value, baseLum); // returns index

t.is(
searchIndex,
5 // list[5] // 3.12 indexed at 5
);
});

test('should return index of exact match (descending)', function(t) {
let list = [12, 5, 3.3, 3.14, 3.13, 3.12, 3.1, 3.07, 3, 2, 1];
let value = 3.12;
let baseLum = 0.3;
let searchIndex = binarySearch(list, value, baseLum); // returns index

t.is(
searchIndex,
5 // list[5] // 3.12 indexed at 5
);
});

test('should return index of closest match (ascending)', function(t) {
let list = [1, 2, 3, 3.07, 3.1, 3.12, 3.13, 3.14, 3.3, 5, 12];
let value = 3.09;
let baseLum = 0.7;
let searchIndex = binarySearch(list, value, baseLum); // returns index

t.is(
searchIndex,
4 // list[4] // 3.1 indexed at 4
);
});

test('should return exact match (ascending)', function(t) {
let list = [1, 2, 3, 3.07, 3.1, 3.12, 3.13, 3.14, 3.3, 5, 12];
let value = 3.12;
let baseLum = 0.7;
let searchResult = binarySearch(list, value, baseLum);
let searchIndex = binarySearch(list, value, baseLum); // returns index
let searchResult = list[searchIndex];

t.is(
searchResult,
Expand All @@ -28,7 +65,8 @@ test('should return exact match (descending)', function(t) {
let list = [12, 5, 3.3, 3.14, 3.13, 3.12, 3.1, 3.07, 3, 2, 1];
let value = 3.12;
let baseLum = 0.3;
let searchResult = binarySearch(list, value, baseLum);
let searchIndex = binarySearch(list, value, baseLum); // returns index
let searchResult = list[searchIndex];

t.is(
searchResult,
Expand All @@ -40,7 +78,8 @@ test('should return closest match (ascending)', function(t) {
let list = [1, 2, 3, 3.07, 3.1, 3.12, 3.13, 3.14, 3.3, 5, 12];
let value = 3.09;
let baseLum = 0.7;
let searchResult = binarySearch(list, value, baseLum);
let searchIndex = binarySearch(list, value, baseLum); // returns index
let searchResult = list[searchIndex];

t.is(
searchResult,
Expand Down

0 comments on commit 2f5dff7

Please sign in to comment.