Ответ 1
Преобразуйте цвета из RGB в HSV или HSL, а затем отсортируйте их по значению или легкости. Легкость может работать лучше, так как она будет захватывать "выцветшие" цвета лучше, например, розовый → красный → темно-красный.
У меня длинный список (1000+) шестицветных цветов, разбитых в общих цветовых категориях (красный, оранжевый, синий и т.д.). Когда я показываю список цветов в каждой категории, мне нужно показать их в порядке тени. то есть сначала светло-красный и темно-красный.
Каким будет алгоритм? (googling провалил меня)
Преобразуйте цвета из RGB в HSV или HSL, а затем отсортируйте их по значению или легкости. Легкость может работать лучше, так как она будет захватывать "выцветшие" цвета лучше, например, розовый → красный → темно-красный.
Я знаю, что этот вопрос старый, но я не нашел довольно эффективного решения этой проблемы, поэтому я немного разбираюсь и хочу поделиться тем, что я сделал для гипотетических будущих гуглеров.
Во-первых, конвертировать в HSL - отличная идея. Но сортировка только по оттенку или свету не решила полностью проблему, когда ваш цвет не "классифицирован".
Учитывая массив, который выглядит следующим образом:
$colors = [
[ 'color' => '#FDD4CD'],
[ 'color' => '#AE3B3B'],
[ 'color' => '#DB62A0'],
...
]
foreach ($colors as &$color) {
$color['hsl'] = hexToHsl($color['color']);
}
/**
* Convert a hexadecimal color in RGB
* @param string $hex
* @return array
*/
function hexToHsl($hex){
list($r, $g, $b) = sscanf($hex, "#%02x%02x%02x");
return rgbToHsl($r, $g, $b);
}
/**
* Convert a RGB color in its HSL value
* @param int $r red
* @param int $g green
* @param int $b blue
* @return array
*/
function rgbToHsl($r, $g, $b)
{
$r /= 255;
$g /= 255;
$b /= 255;
$max = max($r, $g, $b);
$min = min($r, $g, $b);
$h = 0;
$l = ($max + $min) / 2;
$d = $max - $min;
if ($d == 0) {
$h = $s = 0; // achromatic
} else {
$s = $d / (1 - abs(2 * $l - 1));
switch ($max) {
case $r:
$h = 60 * fmod((($g - $b) / $d), 6);
if ($b > $g) {
$h += 360;
}
break;
case $g:
$h = 60 * (($b - $r) / $d + 2);
break;
case $b:
$h = 60 * (($r - $g) / $d + 4);
break;
}
}
return array('h' => round($h, 2), 's' => round($s, 2), 'l' => round($l, 2));
}
Сравним:
Итак:
usort($colors, function ($a, $b) {
//Compare the hue when they are in the same "range"
if(!huesAreinSameInterval($a['hsl']['h'],$b['hsl']['h'])){
if ($a['hsl']['h'] < $b['hsl']['h'])
return -1;
if ($a['hsl']['h'] > $b['hsl']['h'])
return 1;
}
if ($a['hsl']['l'] < $b['hsl']['l'])
return 1;
if ($a['hsl']['l'] > $b['hsl']['l'])
return -1;
if ($a['hsl']['s'] < $b['hsl']['s'])
return -1;
if ($a['hsl']['s'] > $b['hsl']['s'])
return 1;
return 0;
});
/**
* Check if two hues are in the same given interval
* @param float $hue1
* @param float $hue2
* @param int $interval
* @return bool
*/
function huesAreinSameInterval($hue1, $hue2, $interval = 30){
return (round(($hue1 / $interval), 0, PHP_ROUND_HALF_DOWN) === round(($hue2 / $interval), 0, PHP_ROUND_HALF_DOWN));
}
rgbToHsl найдено на www.brandonheyer.com
hexToRgb, найденный на fooobar.com/questions/136450/...
Если вы конвертируете цвета в пространство HSV, вы можете отсортировать их по оттенку, а затем по значению.
Оттенок будет определять цвет "категория" - то есть красный, синий, зеленый и т.д.
Значение и насыщенность будут влиять на "легкость" конечного цвета. Возможно, вам понадобится эксперимент, чтобы получить идеальный вид.