在两个维度上对颜色进行排序

3

为了满足一个网站项目的需求,我想从一组预定义的颜色中生成一个颜色选择器。以下是我的做法:

unsorted color picker

正如您所见,颜色并没有排序。我找到了很多用于排序颜色的算法,但没有2D算法。我想要的结果是这样的:

sorted color picker

你有任何想法我可以做什么吗?谢谢。

如果您想知道,我已经看到了 this post,但问题不同:我不知道50%颜色的最终位置。

这是一种按x轴上的红色和y轴上的绿色排序的尝试:

red green sorted color picker


1
按照红色水平排序,绿色垂直排序。 - Jonas Wilms
你最后一张图片是从哪里得来的?这个来源是否包含更多信息? - Nina Scholz
我从Gimp得到了这张图片。 - Cl00e9ment
我已经尝试了你提出的方法(我编辑了第一篇帖子)。结果并不令人难以置信。 - Cl00e9ment
3个回答

3
感谢你的帮助,Danny_dsHarsh Gupta。 我试图制作一个在X和Y轴上都很平滑的颜色选择器。我尝试了许多不同的算法,但效果并不好。所以现在,我只在一个轴上排序,然后对每一行进行排序。结果看起来非常好: sorted color picker 这是源代码:

'use strict';

let colors = [{
  "name": "Black",
  "hexa": "000000"
 },
 {
  "name": "Sable",
  "hexa": "202020"
 },
 {
  "name": "Grey/Gray",
  "hexa": "808080"
 },
 {
  "name": "Argent",
  "hexa": "E5E5E5"
 },
 {
  "name": "Silver",
  "hexa": "C0C0C0"
 },
 {
  "name": "White",
  "hexa": "FFFFFF"
 },
 {
  "name": "Snow",
  "hexa": "FFFAFA"
 },
 {
  "name": "Gainsboro",
  "hexa": "DCDCDC"
 },
 {
  "name": "Linen",
  "hexa": "FAF0E6"
 },
 {
  "name": "Wheat",
  "hexa": "F5DEB3"
 },
 {
  "name": "Antiquewhite",
  "hexa": "FAEBD7"
 },
 {
  "name": "Darkgray",
  "hexa": "A9A9A9"
 },
 {
  "name": "Dimgray",
  "hexa": "696969"
 },
 {
  "name": "Floralwhite",
  "hexa": "FFFAF0"
 },
 {
  "name": "Ghostwhite",
  "hexa": "F8F8FF"
 },
 {
  "name": "Lightgray",
  "hexa": "D3D3D3"
 },
 {
  "name": "Lightslategray",
  "hexa": "778899"
 },
 {
  "name": "Red",
  "hexa": "FF0100"
 },
 {
  "name": "Brown",
  "hexa": "A52A2A"
 },
 {
  "name": "Maroon",
  "hexa": "800000"
 },
 {
  "name": "Gules",
  "hexa": "DD0100"
 },
 {
  "name": "Crimson",
  "hexa": "DC143C"
 },
 {
  "name": "Indianred",
  "hexa": "CD5C5C"
 },
 {
  "name": "Orangered",
  "hexa": "FF4501"
 },
 {
  "name": "Mistyrose",
  "hexa": "FFE4E1"
 },
 {
  "name": "Darkred",
  "hexa": "8B0000"
 },
 {
  "name": "Firebrick",
  "hexa": "B22222"
 },
 {
  "name": "Lightsalmon",
  "hexa": "FFA07A"
 },
 {
  "name": "Orange",
  "hexa": "FFA502"
 },
 {
  "name": "Gold",
  "hexa": "FFD702"
 },
 {
  "name": "Or",
  "hexa": "FFE403"
 },
 {
  "name": "Chocolate",
  "hexa": "D2691E"
 },
 {
  "name": "Coral",
  "hexa": "FF7F50"
 },
 {
  "name": "Lightcoral",
  "hexa": "F08080"
 },
 {
  "name": "Moccasin",
  "hexa": "FFE4B5"
 },
 {
  "name": "Navajowhite",
  "hexa": "FFDEAD"
 },
 {
  "name": "Darkorange",
  "hexa": "FF8C01"
 },
 {
  "name": "Yellow",
  "hexa": "FFFF03"
 },
 {
  "name": "Tan",
  "hexa": "D2B48C"
 },
 {
  "name": "Bisque",
  "hexa": "FFE4C4"
 },
 {
  "name": "Ivory",
  "hexa": "FFFFF0"
 },
 {
  "name": "Beige",
  "hexa": "F5F5DC"
 },
 {
  "name": "Cornsilk",
  "hexa": "FFF8DC"
 },
 {
  "name": "Goldenrod",
  "hexa": "DAA520"
 },
 {
  "name": "Khaki",
  "hexa": "F0E68C"
 },
 {
  "name": "Lemonchiffon",
  "hexa": "FFFACD"
 },
 {
  "name": "Blanchedalmond",
  "hexa": "FFEBCD"
 },
 {
  "name": "Burlywood",
  "hexa": "DEB887"
 },
 {
  "name": "Darkgoldenrod",
  "hexa": "B8860B"
 },
 {
  "name": "Darkkhaki",
  "hexa": "BDB76B"
 },
 {
  "name": "Yellowgreen",
  "hexa": "9ACD32"
 },
 {
  "name": "Lightgoldenrodyellow",
  "hexa": "FAFAD2"
 },
 {
  "name": "Lightyellow",
  "hexa": "FFFFE0"
 },
 {
  "name": "Oldlace",
  "hexa": "FDF5E6"
 },
 {
  "name": "Palegoldenrod",
  "hexa": "EEE8AA"
 },
 {
  "name": "Papayawhip",
  "hexa": "FFEFD5"
 },
 {
  "name": "Green",
  "hexa": "018001"
 },
 {
  "name": "Vert",
  "hexa": "019301"
 },
 {
  "name": "Lime",
  "hexa": "04FF03"
 },
 {
  "name": "LightGreen",
  "hexa": "90EE90"
 },
 {
  "name": "Olive",
  "hexa": "808001"
 },
 {
  "name": "Chartreuse",
  "hexa": "7FFF03"
 },
 {
  "name": "Honeydew",
  "hexa": "F0FFF0"
 },
 {
  "name": "Springgreen",
  "hexa": "06FF7F"
 },
 {
  "name": "Mediumseagreen",
  "hexa": "3CB371"
 },
 {
  "name": "Lawngreen",
  "hexa": "7CFC03"
 },
 {
  "name": "Darkgreen",
  "hexa": "016400"
 },
 {
  "name": "Darkolivegreen",
  "hexa": "556B2F"
 },
 {
  "name": "Seagreen",
  "hexa": "2E8B57"
 },
 {
  "name": "Darkseagreen",
  "hexa": "8FBC8F"
 },
 {
  "name": "Darkslategray",
  "hexa": "2F4F4F"
 },
 {
  "name": "Forestgreen",
  "hexa": "228B22"
 },
 {
  "name": "Greenyellow",
  "hexa": "ADFF2F"
 },
 {
  "name": "Lightseagreen",
  "hexa": "20B2AA"
 },
 {
  "name": "Mediumaquamarine",
  "hexa": "66CDAA"
 },
 {
  "name": "Mediumspringgreen",
  "hexa": "07FA9A"
 },
 {
  "name": "Mintcream",
  "hexa": "F5FFFA"
 },
 {
  "name": "Palegreen",
  "hexa": "98FB98"
 },
 {
  "name": "Azure/Blue",
  "hexa": "0800FF"
 },
 {
  "name": "Teal",
  "hexa": "038080"
 },
 {
  "name": "Cyan/Aqua",
  "hexa": "0CFFFF"
 },
 {
  "name": "Turquoise",
  "hexa": "40E0D0"
 },
 {
  "name": "Lightblue",
  "hexa": "ADD8E6"
 },
 {
  "name": "Navy",
  "hexa": "020080"
 },
 {
  "name": "Lightcyan",
  "hexa": "E0FFFF"
 },
 {
  "name": "Midnightblue",
  "hexa": "191970"
 },
 {
  "name": "Slateblue",
  "hexa": "6A5ACD"
 },
 {
  "name": "Cadetblue",
  "hexa": "5F9EA0"
 },
 {
  "name": "Aliceblue",
  "hexa": "F0F8FF"
 },
 {
  "name": "Aquamarine",
  "hexa": "7FFFD4"
 },
 {
  "name": "Cornflowerblue",
  "hexa": "6495ED"
 },
 {
  "name": "Darkblue",
  "hexa": "02008B"
 },
 {
  "name": "Darkcyan",
  "hexa": "038B8B"
 },
 {
  "name": "Darkslateblue",
  "hexa": "483D8B"
 },
 {
  "name": "Darkturquoise",
  "hexa": "08CED1"
 },
 {
  "name": "Deepskyblue",
  "hexa": "0ABFFF"
 },
 {
  "name": "Dodgerblue",
  "hexa": "1E90FF"
 },
 {
  "name": "Lightskyblue",
  "hexa": "87CEFA"
 },
 {
  "name": "Lightsteelblue",
  "hexa": "B0C4DE"
 },
 {
  "name": "Mediumslateblue",
  "hexa": "7B68EE"
 },
 {
  "name": "Mediumturquoise",
  "hexa": "48D1CC"
 },
 {
  "name": "Paleturquoise",
  "hexa": "AFEEEE"
 },
 {
  "name": "Indigo",
  "hexa": "4B0082"
 },
 {
  "name": "Violet",
  "hexa": "EE82EE"
 },
 {
  "name": "Purple",
  "hexa": "800080"
 },
 {
  "name": "Lavender",
  "hexa": "E6E6FA"
 },
 {
  "name": "Plum",
  "hexa": "DDA0DD"
 },
 {
  "name": "Mediumpurple",
  "hexa": "9370DB"
 },
 {
  "name": "Blueviolet",
  "hexa": "8A2BE2"
 },
 {
  "name": "Darkmagenta",
  "hexa": "8B008B"
 },
 {
  "name": "Darkviolet",
  "hexa": "9400D3"
 },
 {
  "name": "Pink",
  "hexa": "FFC0CB"
 },
 {
  "name": "Fuchsia/Magenta",
  "hexa": "FF00FF"
 },
 {
  "name": "Purpure",
  "hexa": "B31F85"
 },
 {
  "name": "Orchid",
  "hexa": "DA70D6"
 },
 {
  "name": "Hotpink",
  "hexa": "FF69B4"
 },
 {
  "name": "Darkorchid",
  "hexa": "9932CC"
 },
 {
  "name": "Darksalmon",
  "hexa": "E9967A"
 },
 {
  "name": "Deeppink",
  "hexa": "FF1493"
 },
 {
  "name": "Lavenderblush",
  "hexa": "FFF0F5"
 },
 {
  "name": "Lightpink",
  "hexa": "FFB6C1"
 }
];

function hexToRgbColor(hexColor) {
 return [
  parseInt(hexColor.substr(0, 2), 16),
  parseInt(hexColor.substr(2, 2), 16),
  parseInt(hexColor.substr(4, 2), 16)
 ];
}

function rgbToHsvColor(rgbColor) {

 const r = rgbColor[0];
 const g = rgbColor[1];
 const b = rgbColor[2];

 let rabs, gabs, babs, rr, gg, bb, h, s, v, diff, diffc, percentRoundFn;
 rabs = r / 255;
 gabs = g / 255;
 babs = b / 255;
 v = Math.max(rabs, gabs, babs);
 diff = v - Math.min(rabs, gabs, babs);
 diffc = c => (v - c) / 6 / diff + 1 / 2;
 percentRoundFn = num => Math.round(num * 100) / 100;
 if (diff == 0) {
  h = s = 0;
 } else {
  s = diff / v;
  rr = diffc(rabs);
  gg = diffc(gabs);
  bb = diffc(babs);

  if (rabs === v) {
   h = bb - gg;
  } else if (gabs === v) {
   h = (1 / 3) + rr - bb;
  } else if (babs === v) {
   h = (2 / 3) + gg - rr;
  }
  if (h < 0) {
   h += 1;
  } else if (h > 1) {
   h -= 1;
  }
 }
 return [
  Math.round(h * 360),
  percentRoundFn(s * 100),
  percentRoundFn(v * 100)
 ];
}

function rgbToLuminance(rgbColor) {
  return Math.sqrt(.299*rgbColor[0]*rgbColor[0] + .587*rgbColor[1]*rgbColor[1] + .114*rgbColor[2]*rgbColor[2]);
}

function sortArray(array, compareValueGetter) {

 array.sort((elem1, elem2) => {
  const value1 = compareValueGetter(elem1);
  const value2 = compareValueGetter(elem2);
  return value1 > value2 ? 1 : (value1 < value2 ? -1 : 0);
 });
}

const nbOfColumns = 11;
const palette = document.getElementById('palette');

for (const color of colors) {
 color.rgb = hexToRgbColor(color.hexa);
 color.hsv = rgbToHsvColor(color.rgb, false);
 color.luminance = rgbToLuminance(color.rgb);
}

sortArray(colors, color => color.hsv[0]);

let sortedColors = [];
let line;

while (colors.length > 0) {

 line = colors.splice(0, nbOfColumns);
 sortArray(line, color => color.luminance)
 sortedColors = sortedColors.concat(line);
}

let tile;
for (const color of sortedColors) {
 tile = document.createElement('div');
 tile.style.backgroundColor = '#'+color.hexa;
 palette.appendChild(tile);
}
#palette{
 width: 220px;
 display: flex;
 flex-wrap: wrap;
}

#palette>div{
 cursor: pointer;
 width: 20px;
 height: 20px;
}

#palette div:hover::after{
 content: "";
 display: block;
 width: 20px;
 height: 20px;
 border: 2px solid black;
 z-index: 1;
 position: relative;
 top: -2px;
 left: -2px;
}
<!DOCTYPE html>
<html>
<head>
 <meta charset="utf-8" />
 <link rel="stylesheet" type="text/css" media="screen" href="main.css" />
</head>
<body>
 <div id="palette"></div>
</body>
</html>


2
第二张图片不仅仅是一个按某种方式排序的颜色矩阵。实际上,它是一个从某个角度观察的三维颜色模型的截面。颜色模型是一种多维可视化展示颜色光谱的工具。像GIMP这样的工具可以向您展示这种光谱的一个截面。
例如,考虑具有原点顶点(0, 0, 0)的立方体。对于RGB颜色来说,每个轴都是相应色彩值的范围,范围从0到255。沿着X轴,我们有R值从0到255,沿着Y轴,我们有G值从0到255,沿着Z轴,我们有B值从0到255。在原点(0, 0, 0)处,我们有黑色。在相反的端点,我们有顶点(255, 255, 255),即白色。通过改变沿轴的值,您可以获得任何颜色值。
更多详情,请查看:https://programmingdesignsystems.com/color/color-models-and-color-spaces/index.html

2
你可以将颜色从RGB转换为HSL,然后按色相和饱和度(例如x / y)进行排序。
要按照第二个图像中的顺序排列颜色,可以将色相想象成在彩色轮上,并将其转换为适合你的正方形或矩形的x / y位置。
或者,您可以根据评论中已经提到的红/绿(x / y)进行排序(您显示的额外图像没有按红/绿排序)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接