96 lines
2.5 KiB
TypeScript
96 lines
2.5 KiB
TypeScript
![]() |
import { isValidColor, getHsl, getDeltaE, transformHslToHex } from './color';
|
||
|
import { getColorName } from './name';
|
||
|
import type { ColorPaletteFamily, ColorPaletteFamilyWithNearestPalette } from './type';
|
||
|
import defaultPalettes from './json/palette.json';
|
||
|
|
||
|
export function getNearestColorPaletteFamily(color: string, families: ColorPaletteFamily[]) {
|
||
|
const familyWithConfig = families.map(family => {
|
||
|
const palettes = family.palettes.map(palette => {
|
||
|
return {
|
||
|
...palette,
|
||
|
delta: getDeltaE(color, palette.hexcode)
|
||
|
};
|
||
|
});
|
||
|
|
||
|
const nearestPalette = palettes.reduce((prev, curr) => (prev.delta < curr.delta ? prev : curr));
|
||
|
|
||
|
return {
|
||
|
...family,
|
||
|
palettes,
|
||
|
nearestPalette
|
||
|
};
|
||
|
});
|
||
|
|
||
|
const nearestPaletteFamily = familyWithConfig.reduce((prev, curr) =>
|
||
|
prev.nearestPalette.delta < curr.nearestPalette.delta ? prev : curr
|
||
|
);
|
||
|
|
||
|
const { l } = getHsl(color);
|
||
|
|
||
|
const paletteFamily: ColorPaletteFamilyWithNearestPalette = {
|
||
|
...nearestPaletteFamily,
|
||
|
nearestLightnessPalette: nearestPaletteFamily.palettes.reduce((prev, curr) => {
|
||
|
const { l: prevLightness } = getHsl(prev.hexcode);
|
||
|
const { l: currLightness } = getHsl(curr.hexcode);
|
||
|
|
||
|
const deltaPrev = Math.abs(prevLightness - l);
|
||
|
const deltaCurr = Math.abs(currLightness - l);
|
||
|
|
||
|
return deltaPrev < deltaCurr ? prev : curr;
|
||
|
})
|
||
|
};
|
||
|
|
||
|
return paletteFamily;
|
||
|
}
|
||
|
|
||
|
export function getColorPaletteFamily(color: string, colorName: string) {
|
||
|
if (!isValidColor(color)) {
|
||
|
throw new Error('Invalid color, please check color value!');
|
||
|
}
|
||
|
|
||
|
const { h: h1, s: s1 } = getHsl(color);
|
||
|
|
||
|
const { nearestLightnessPalette, palettes } = getNearestColorPaletteFamily(
|
||
|
color,
|
||
|
defaultPalettes as ColorPaletteFamily[]
|
||
|
);
|
||
|
|
||
|
const { number, hexcode } = nearestLightnessPalette;
|
||
|
|
||
|
const { h: h2, s: s2 } = getHsl(hexcode);
|
||
|
|
||
|
const deltaH = h1 - h2 || h2;
|
||
|
|
||
|
const sRatio = s1 / s2;
|
||
|
|
||
|
const colorPaletteFamily: ColorPaletteFamily = {
|
||
|
key: colorName,
|
||
|
palettes: palettes.map(palette => {
|
||
|
let hexValue = color;
|
||
|
|
||
|
const isSame = number === palette.number;
|
||
|
|
||
|
if (!isSame) {
|
||
|
const { h: h3, s: s3, l } = getHsl(palette.hexcode);
|
||
|
|
||
|
const newH = deltaH < 0 ? h3 + deltaH : deltaH;
|
||
|
const newS = s3 * sRatio;
|
||
|
|
||
|
hexValue = transformHslToHex({
|
||
|
h: newH,
|
||
|
s: newS,
|
||
|
l
|
||
|
});
|
||
|
}
|
||
|
|
||
|
return {
|
||
|
hexcode: hexValue,
|
||
|
number: palette.number,
|
||
|
name: getColorName(hexValue)
|
||
|
};
|
||
|
})
|
||
|
};
|
||
|
|
||
|
return colorPaletteFamily;
|
||
|
}
|