我正在建造颜色选择器。如果用户选择颜色方块,则会转换为近似颜色名称。
例如,如果用户选择C0C0C0
或BEBEBE
的颜色,即使每种颜色都有特定的颜色名称,两种颜色的字符串也会转换为grey
。
我甚至无法弄清楚我是如何解决这个问题的,谷歌也没有帮助我! :(
这是我的颜色函数的sudo代码
getApproxColor = (colorString) => {
if(`BBBBBB` <= colorString <= 'CCCCCC') {
return 'grey'
}
...
}
我应该在这个函数上写整个颜色名吗?是否有任何十六进制颜色的公式?
答案 0 :(得分:1)
TL; DR:只需使用此库。这是我所说的混合而是由Kaiido提到的复杂性解决:http://chir.ag/projects/ntc/
保留原来的答案,但不会完全奏效。往上看。
嗯,每种颜色都是六位六位数的组合。
如果将该数字转换为int,请说BEBEBE为12500670.
然后,您可以拥有一个小表,其中包含每个已知名称的密钥/对及其对应的整数值。
然后只是在表中找到最接近的整数。
编辑:
基本上,如果你有你的颜色选择器并且说这个人选择'BEBEBE'你就必须:
答案 1 :(得分:1)
我不确定这是否是最佳方式,但如果我不得不做这样的事情,我想我会先将这些十六进制值转换为hsl。
然后你必须检查饱和度和亮度,以便找到灰色并在你的发现中添加更多的粒度。
这是一个粗略的概念证明,仅使用6种基色并使用stolen code from an older question来执行此操作hex =&gt; hsl转换。
inp.oninput = e => {
if (!inp.checkValidity()) return;
var val = inp.value;
if (val.length !== 3 && val.length !== 6) return;
var color = hexToName(inp.value);
if (color) {
inp.style.backgroundColor = '#' + val;
log.textContent = color;
}
}
function hexToName(hex) {
// first get hsl correspondance
var hsl = hexToHsl(hex);
if(!hsl){
return;
}
// get the base color
var color = getColorName(hsl[0] * 360);
// check saturation and luminosity
// needs more granularity, left as an exercise for the reader
if (hsl[1] < .5) {
return hsl[2] <= .5 ? hsl[2] === 0? 'black' : 'darkgray' : hsl[2] === 1 ? 'white': 'gray';
}
return hsl[2] <= .5 ? color : 'light' + color;
}
function getColorName(hue) {
// here you will need more work:
// we use fixed distance for this simple demo
var names = ['red', 'yellow', 'green', 'cyan', 'blue', 'magenta'];
var angles = [0, 60, 120, 180, 240, 300];
var match = angles.filter(a =>
a - 60 <= hue && a + 60 > hue
)[0] || 0;
return names[angles.indexOf(match)];
}
// shamelessly stolen from https://stackoverflow.com/a/3732187/3702797
function hexToHsl(hex) {
if (hex.length === 3) {
hex = hex.split('').map(c => c.repeat(2)).join('');
}
if (hex.length !== 6) {
return;
}
var r = parseInt(hex[0] + hex[1], 16);
var g = parseInt(hex[2] + hex[3], 16);
var b = parseInt(hex[4] + hex[5], 16);
r /= 255, g /= 255, b /= 255;
var max = Math.max(r, g, b),
min = Math.min(r, g, b);
var h, s, l = (max + min) / 2;
if (max == min) {
h = s = 0; // achromatic
} else {
var d = max - min;
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
switch (max) {
case r:
h = (g - b) / d + (g < b ? 6 : 0);
break;
case g:
h = (b - r) / d + 2;
break;
case b:
h = (r - g) / d + 4;
break;
}
h /= 6;
}
return [h, s, l];
}
#<input id="inp" type="text" pattern="[0-9a-fA-F]+">
<pre id="log"><pre>