Created
January 16, 2020 07:30
-
-
Save Munawwar/6df560f2027f5ecb65a4281797e9ab03 to your computer and use it in GitHub Desktop.
leonardocolor.io contrast distribution
This file contains hidden or 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
const d3 = require('d3'); | |
const d3hsluv = require('d3-hsluv'); | |
const { generateContrastColors } = require('./leonardo'); | |
Object.assign(d3, d3hsluv); | |
function interpolateLumArray(newColors) { | |
const lums = []; | |
for (let i = 0; i < newColors.length; i += 1) { | |
lums.push(d3.hsluv(newColors[i]).v); | |
} | |
const startLum = Math.min(...lums); | |
const endLum = Math.max(...lums); | |
const interpolator = d3.interpolateNumber(startLum, endLum); | |
for (let i = 1; i < lums.length - 1; i += 1) { | |
lums[i] = interpolator((i) / (lums.length)); | |
} | |
lums.sort((a, b) => b - a); | |
return lums; | |
} | |
function returnRatioCube(lum) { | |
const a = 1.45; | |
const b = 0.7375; | |
const c = 2.5; | |
const x = lum / 100; | |
const exp = ((x * -1 / a) + b); | |
const y = (exp ** 3) * c; | |
const r = y * 20 + 1; | |
if (r > 1) { | |
return r; | |
} | |
if (r < 1 && r >= 0) { | |
return 1; | |
} | |
return -1; | |
} | |
export const distributeRatios = (newColors) => { | |
const lums = interpolateLumArray(newColors); | |
return lums.map(lum => Number(returnRatioCube(lum).toFixed(2))); | |
}; | |
const cache = {}; | |
export default function generateColors({ | |
numberOfColors = 5, | |
colorKeys = ['#38b2ac', '#112135'], | |
base = '#ffffff', | |
firstRatio = 3, | |
lastRatio = 18, | |
}) { | |
const cacheKey = [ | |
numberOfColors, | |
colorKeys.join(','), | |
base, | |
firstRatio, | |
lastRatio, | |
].join('|'); | |
if (cache[cacheKey]) { | |
return cache[cacheKey]; | |
} | |
const uniformspace = (lastRatio - firstRatio) / numberOfColors; | |
const initialRatios = []; | |
for (let i = 0; i < numberOfColors; i += 1) { | |
initialRatios.push( | |
i === numberOfColors - 1 && i !== 0 | |
? lastRatio | |
: Number((firstRatio + uniformspace * i).toFixed(2)), | |
); | |
} | |
const firstColors = generateContrastColors({ | |
colorKeys, | |
base, | |
ratios: initialRatios, | |
colorspace: 'CAM02', | |
}); | |
const distributedColors = generateContrastColors({ | |
colorKeys, | |
base, | |
ratios: distributeRatios(firstColors), | |
colorspace: 'CAM02', | |
}); | |
cache[cacheKey] = distributedColors; | |
return distributedColors; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Credits: Code ripped off from leonardocolor.io website's source.
To generate leonardo.js used in this example do:
git clone @adobe/leonardo cd leonardo npm install npm install -g rollup rollup packages/contrast-colors/index.js --file leonardo.js --format cjs
Copy leonardo.js to your front-end source directory and also install following modules
I couldn't get direct ESM format working with React CRA/webpack.. so I took this rollup route.