From 343ef7a6e086dee8549f3101331138e8dc2618bc Mon Sep 17 00:00:00 2001 From: Nate Baldwin Date: Tue, 10 Mar 2020 16:02:14 -0600 Subject: [PATCH 1/7] added domain for clamped colors --- packages/contrast-colors/index.js | 66 ++++++++++++++++++++----------- packages/ui/src/index.html | 5 ++- 2 files changed, 47 insertions(+), 24 deletions(-) diff --git a/packages/contrast-colors/index.js b/packages/contrast-colors/index.js index 0f8a759b..128e9c3f 100644 --- a/packages/contrast-colors/index.js +++ b/packages/contrast-colors/index.js @@ -239,6 +239,13 @@ function removeDuplicates(originalArray, prop) { return newArray; } +function normalizePercent(min, max, input) { + let range = max - min; + let correctedStartValue = input - min; + let percentage = (correctedStartValue * 100) / range; + return percentage / 100; +} + function createScale({ swatches, colorKeys, @@ -252,28 +259,10 @@ function createScale({ throw new Error(`Colorspace “${colorspace}” not supported`); } - 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) - let sqrtDomains = d3.scalePow() - .exponent(shift) - .domain([1, swatches]) - .range([1, swatches]); - - sqrtDomains = domains.map((d) => { - if (sqrtDomains(d) < 0) { - return 0; - } - return sqrtDomains(d); - }); + let domains; + let ColorsArray = []; + let scale; - // Transform square root in order to smooth gradient - domains = sqrtDomains; let sortedColor = colorKeys // Convert to HSLuv and keep track of original indices @@ -291,14 +280,29 @@ function createScale({ // Retrieve original RGB color .map(data => colorKeys[data.index]); - let ColorsArray = []; - let scale; if (fullScale) { + domains = colorKeys + .map(key => swatches - swatches * (d3.hsluv(key).v / 100)) + .sort((a, b) => a - b) + .concat(swatches); + + domains.unshift(0); + ColorsArray = [space.white || '#fff', ...sortedColor, space.black || '#000']; } else { + let tempDomains = colorKeys + .map(key => d3.hsluv(key).v / 100) + .sort((a, b) => a - b); + + let min = Math.min(...tempDomains); + let max = Math.max(...tempDomains); + + domains = tempDomains.map(key => normalizePercent(min, max, key)); + ColorsArray = sortedColor; } + const stringColors = ColorsArray; ColorsArray = ColorsArray.map(d => d3[space.name](d)); if (space.name == 'hcl') { @@ -316,6 +320,22 @@ function createScale({ } } + // Test logarithmic domain (for non-contrast-based scales) + let sqrtDomains = d3.scalePow() + .exponent(shift) + .domain([1, swatches]) + .range([1, swatches]); + + sqrtDomains = domains.map((d) => { + if (sqrtDomains(d) < 0) { + return 0; + } + return sqrtDomains(d); + }); + + // Transform square root in order to smooth gradient + domains = sqrtDomains; + if (smooth) { scale = smoothScale(ColorsArray, domains, space); } else { diff --git a/packages/ui/src/index.html b/packages/ui/src/index.html index 93332374..b6f8ea5c 100644 --- a/packages/ui/src/index.html +++ b/packages/ui/src/index.html @@ -119,11 +119,13 @@

Key Colors

- +
From ad30d98d7b43bc3f5316603c4766ec4e13b7dde7 Mon Sep 17 00:00:00 2001 From: Nate Baldwin Date: Tue, 10 Mar 2020 16:04:43 -0600 Subject: [PATCH 2/7] added UI toggle for configs --- packages/ui/src/index.html | 4 ++-- packages/ui/src/index.js | 23 +++++++++++++++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/packages/ui/src/index.html b/packages/ui/src/index.html index b6f8ea5c..84053b27 100644 --- a/packages/ui/src/index.html +++ b/packages/ui/src/index.html @@ -124,8 +124,8 @@

Key Colors

diff --git a/packages/ui/src/index.js b/packages/ui/src/index.js index 2335f11d..3a4cb33d 100644 --- a/packages/ui/src/index.js +++ b/packages/ui/src/index.js @@ -583,6 +583,29 @@ function checkRatioStepModifiers(e) { } } + +window.changePalette = changePalette; +function changePalette() { + var paletteType = document.getElementById('paletteType').value; + var wrapSequence = document.getElementById('sequentialConfigs'); + var wrapRatio = document.getElementById('contrastConfigs'); + var sliders = document.getElementById('sliderWrapper'); + + if (paletteType == 'Contrast') { + wrapSequence.style.display = 'none'; + wrapRatio.style.display = 'flex'; + // sliders.style.display = 'flex'; + } + if (paletteType == 'Sequential') { + wrapSequence.style.display = 'flex'; + wrapRatio.style.display = 'none'; + // sliders.style.display = 'none'; + } + + colorInput(); +} + + // Calculate Color and generate Scales window.colorInput = colorInput; function colorInput() { From 5bc35974af0842b14b9a6912559c1b9856de67d3 Mon Sep 17 00:00:00 2001 From: Nate Baldwin Date: Tue, 10 Mar 2020 16:08:57 -0600 Subject: [PATCH 3/7] copied code from old branch for sequential conditions in ui --- packages/ui/src/index.js | 79 +++++++++++++++++++++++++++++++++------- 1 file changed, 65 insertions(+), 14 deletions(-) diff --git a/packages/ui/src/index.js b/packages/ui/src/index.js index 3a4cb33d..24379461 100644 --- a/packages/ui/src/index.js +++ b/packages/ui/src/index.js @@ -610,6 +610,15 @@ function changePalette() { window.colorInput = colorInput; function colorInput() { document.getElementById('colorScale').innerHTML = ''; + + let paletteTypeInput = document.getElementById('paletteType'); + let paletteType = paletteTypeInput.value; + let shiftInput = document.getElementById('shiftInput'); + let shift = shiftInput.value; + let shiftInputValueLabel = document.getElementById('shiftInputValue'); + shiftInputValueLabel.innerHTML = shift; + let swatchAmmount = document.getElementById('swatchAmmount').value; + let spaceOpt = document.getElementById('chart3dColorspace').value; var inputs = document.getElementsByClassName('keyColor-Item'); @@ -655,7 +664,15 @@ function colorInput() { let rampData = contrastColors.createScale({swatches: n, colorKeys: colorArgs, colorspace: mode, shift: shift}); - newColors = contrastColors.generateContrastColors({colorKeys: colorArgs, base: background, ratios: ratioInputs, colorspace: mode, shift: shift}); + // newColors = contrastColors.generateContrastColors({colorKeys: colorArgs, base: background, ratios: ratioInputs, colorspace: mode, shift: shift}); + let newColors; + if (paletteType == 'Contrast') { + newColors = contrastColors.generateContrastColors({colorKeys: colorArgs, base: background, ratios: ratioInputs, colorspace: mode, shift: shift}); + } + if (paletteType == 'Sequential') { + newColors = contrastColors.generateSequentialColors({swatches: swatchAmmount, colorKeys: colorArgs, colorspace: mode, shift: shift, fullScale: clamping}); + } + // Create values for sliders let Values = []; @@ -684,23 +701,57 @@ function colorInput() { } else { return sqrtValues(d); } - }) + }); - for(let i=0; i Date: Tue, 10 Mar 2020 17:00:59 -0600 Subject: [PATCH 4/7] feat: added option to not have optically balanced scale, added UI controls for fullscale, corrected output for sequential swatches --- packages/contrast-colors/index.js | 82 ++++++++++++++++++++++++++++--- packages/ui/src/index.html | 18 ++++++- packages/ui/src/index.js | 22 ++++++--- 3 files changed, 106 insertions(+), 16 deletions(-) diff --git a/packages/contrast-colors/index.js b/packages/contrast-colors/index.js index 128e9c3f..4d911dc9 100644 --- a/packages/contrast-colors/index.js +++ b/packages/contrast-colors/index.js @@ -252,7 +252,8 @@ function createScale({ colorspace = 'LAB', shift = 1, fullScale = true, - smooth = false + smooth = false, + correctLightness = true } = {}) { const space = colorSpaces[colorspace]; if (!space) { @@ -263,7 +264,6 @@ function createScale({ let ColorsArray = []; let scale; - let sortedColor = colorKeys // Convert to HSLuv and keep track of original indices .map((c, i) => { return { colorKeys: cArray(c), index: i } }) @@ -290,19 +290,29 @@ function createScale({ domains.unshift(0); ColorsArray = [space.white || '#fff', ...sortedColor, space.black || '#000']; - } else { + } + else if (!fullScale) { let tempDomains = colorKeys - .map(key => d3.hsluv(key).v / 100) + .map(key => swatches - swatches * (d3.hsluv(key).v / 100)) .sort((a, b) => a - b); let min = Math.min(...tempDomains); let max = Math.max(...tempDomains); - domains = tempDomains.map(key => normalizePercent(min, max, key)); - + domains = tempDomains.map(key => normalizePercent(min, max, key) * swatches); + console.log(domains); ColorsArray = sortedColor; } + if(!correctLightness) { + domains = []; + for (let i=0; i < ColorsArray.length; i++) { + let p = 1 / (ColorsArray.length - 1); + let c = i * p; + domains.push(c * swatches); + } + } + const stringColors = ColorsArray; ColorsArray = ColorsArray.map(d => d3[space.name](d)); if (space.name == 'hcl') { @@ -336,16 +346,37 @@ function createScale({ // Transform square root in order to smooth gradient domains = sqrtDomains; + console.log("Colors : " + ColorsArray); + // console.log(domains); + if (smooth) { scale = smoothScale(ColorsArray, domains, space); } else { scale = d3.scaleLinear() - .range(ColorsArray) .domain(domains) + .range(ColorsArray) .interpolate(space.interpolator); } - let Colors = d3.range(swatches).map(d => scale(d)); + let Colors = []; + + if(fullScale) { + // Colors = d3.range(swatches).map(d => scale(d)); + let inc = 1 / (swatches - 2); + for(let i = 0; i < swatches; i++) { + let currentInc = inc * i; + let color = scale(currentInc * swatches); + Colors.push(color); + } + } + else if (!fullScale) { + let inc = 1 / (swatches - 1); + for(let i = 0; i < swatches; i++) { + let currentInc = inc * i; + let color = scale(currentInc * swatches); + Colors.push(color); + } + } let colors = Colors.filter(el => el != null); @@ -649,6 +680,40 @@ function binarySearch(list, value, baseLum) { return (list[middle] == !value) ? closest : middle // how it was originally expressed } + +function generateSequentialColors( + { + swatches = 8, + colorKeys, + colorspace = 'LAB', + shift = 1, + fullScale = true, + correctLightness = true + } = {}) { + + let sequenceData = createScale({swatches: swatches, colorKeys: colorKeys, colorspace: colorspace, shift: shift, fullScale: fullScale, correctLightness: correctLightness}); + let colorRange = sequenceData.colors; + + let fillDomain = []; + for(let i=0; iKey Colors
+
+
+ +
+
+
diff --git a/packages/ui/src/index.js b/packages/ui/src/index.js index 24379461..985d0c0e 100644 --- a/packages/ui/src/index.js +++ b/packages/ui/src/index.js @@ -614,9 +614,19 @@ function colorInput() { let paletteTypeInput = document.getElementById('paletteType'); let paletteType = paletteTypeInput.value; let shiftInput = document.getElementById('shiftInput'); - let shift = shiftInput.value; + let shift; + if (paletteType == 'Contrast') { + shift = 1; + } + else if (paletteType == 'Sequential') { + shift = shiftInput.value; + } let shiftInputValueLabel = document.getElementById('shiftInputValue'); shiftInputValueLabel.innerHTML = shift; + + let lightnessCorrectionInput = document.getElementById('opticalScale'); + let correctLightness = lightnessCorrectionInput.checked; + let swatchAmmount = document.getElementById('swatchAmmount').value; let spaceOpt = document.getElementById('chart3dColorspace').value; @@ -628,7 +638,7 @@ function colorInput() { // Clamp ratios convert decimal numbers to whole negatives and disallow // inputs less than 1 and greater than -1. for(let i=0; i -1) { ratioFields[i].value = (10 / (val * 10)).toFixed(2) * -1; } else { } @@ -655,14 +665,14 @@ function colorInput() { tempArgs.push(inputColors); colorArgs = tempArgs.join("").split(',').filter(String); - let shift = 1; let clamping = document.getElementById('sequentialClamp').checked; + console.log(clamping); // Generate scale data so we have access to all 3000 swatches to draw the gradient on the left - let scaleData = contrastColors.createScale({swatches: 3000, colorKeys: colorArgs, colorspace: mode, shift: shift}); + let scaleData = contrastColors.createScale({swatches: 3000, colorKeys: colorArgs, colorspace: mode, shift: shift, correctLightness: correctLightness}); let n = window.innerHeight - 282; - let rampData = contrastColors.createScale({swatches: n, colorKeys: colorArgs, colorspace: mode, shift: shift}); + let rampData = contrastColors.createScale({swatches: n, colorKeys: colorArgs, colorspace: mode, shift: shift, correctLightness: correctLightness}); // newColors = contrastColors.generateContrastColors({colorKeys: colorArgs, base: background, ratios: ratioInputs, colorspace: mode, shift: shift}); let newColors; @@ -670,7 +680,7 @@ function colorInput() { newColors = contrastColors.generateContrastColors({colorKeys: colorArgs, base: background, ratios: ratioInputs, colorspace: mode, shift: shift}); } if (paletteType == 'Sequential') { - newColors = contrastColors.generateSequentialColors({swatches: swatchAmmount, colorKeys: colorArgs, colorspace: mode, shift: shift, fullScale: clamping}); + newColors = contrastColors.generateSequentialColors({swatches: swatchAmmount, colorKeys: colorArgs, colorspace: mode, shift: shift, fullScale: clamping, correctLightness: correctLightness}); } From d151d1ca3fd1706fb12d29918b324f3506f79d00 Mon Sep 17 00:00:00 2001 From: Nate Baldwin Date: Wed, 11 Mar 2020 09:56:18 -0600 Subject: [PATCH 5/7] added arguments to change presentation of ramp and visualizations based on clamping and correcting lightness --- packages/ui/src/charts.js | 5 ++++- packages/ui/src/index.js | 5 ++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/ui/src/charts.js b/packages/ui/src/charts.js index 655ccbb9..8c8d8a67 100644 --- a/packages/ui/src/charts.js +++ b/packages/ui/src/charts.js @@ -569,11 +569,14 @@ let chartColors = []; function getChartColors(mode) { let shift = document.getElementById('shiftInput').value; + let lightnessCorrectionInput = document.getElementById('opticalScale'); + let correctLightness = lightnessCorrectionInput.checked; + let clamping = document.getElementById('sequentialClamp').checked; let chartColors = []; // GENERATE PROPER SCALE OF COLORS FOR 3d CHART: - let chartRGB = contrastColors.createScale({swatches: 340, colorKeys: colorArgs, colorspace: mode, shift: shift}); + let chartRGB = contrastColors.createScale({swatches: 340, colorKeys: colorArgs, colorspace: mode, fullScale: clamping, shift: shift, correctLightness: correctLightness}); for (let i=0; i Date: Mon, 16 Mar 2020 15:35:21 -0600 Subject: [PATCH 6/7] properly generating sequential colors as expected when clamped and fullscale --- packages/contrast-colors/index.js | 58 ++--- .../test/generateSequentialColors.test.js | 77 ++++++ packages/ui/src/index.html | 6 +- packages/ui/src/index.js | 229 ++++++++++++------ 4 files changed, 272 insertions(+), 98 deletions(-) create mode 100644 packages/contrast-colors/test/generateSequentialColors.test.js diff --git a/packages/contrast-colors/index.js b/packages/contrast-colors/index.js index 4d911dc9..46237568 100644 --- a/packages/contrast-colors/index.js +++ b/packages/contrast-colors/index.js @@ -285,7 +285,7 @@ function createScale({ domains = colorKeys .map(key => swatches - swatches * (d3.hsluv(key).v / 100)) .sort((a, b) => a - b) - .concat(swatches); + .concat(Number(swatches)); domains.unshift(0); @@ -300,7 +300,7 @@ function createScale({ let max = Math.max(...tempDomains); domains = tempDomains.map(key => normalizePercent(min, max, key) * swatches); - console.log(domains); + ColorsArray = sortedColor; } @@ -333,8 +333,8 @@ function createScale({ // Test logarithmic domain (for non-contrast-based scales) let sqrtDomains = d3.scalePow() .exponent(shift) - .domain([1, swatches]) - .range([1, swatches]); + .domain([0, swatches]) + .range([0, swatches]); sqrtDomains = domains.map((d) => { if (sqrtDomains(d) < 0) { @@ -346,9 +346,6 @@ function createScale({ // Transform square root in order to smooth gradient domains = sqrtDomains; - console.log("Colors : " + ColorsArray); - // console.log(domains); - if (smooth) { scale = smoothScale(ColorsArray, domains, space); } else { @@ -362,7 +359,7 @@ function createScale({ if(fullScale) { // Colors = d3.range(swatches).map(d => scale(d)); - let inc = 1 / (swatches - 2); + let inc = 1 / (swatches - 1); for(let i = 0; i < swatches; i++) { let currentInc = inc * i; let color = scale(currentInc * swatches); @@ -683,36 +680,43 @@ function binarySearch(list, value, baseLum) { function generateSequentialColors( { - swatches = 8, + swatches, colorKeys, colorspace = 'LAB', shift = 1, fullScale = true, - correctLightness = true + correctLightness = true, + smooth = false } = {}) { - let sequenceData = createScale({swatches: swatches, colorKeys: colorKeys, colorspace: colorspace, shift: shift, fullScale: fullScale, correctLightness: correctLightness}); - let colorRange = sequenceData.colors; - - let fillDomain = []; - for(let i=0; iKey Colors
- @@ -155,7 +155,7 @@

Key Colors