javascript - 排序颜色/颜色值

标签 javascript arrays sorting colors alignment

我希望尽可能精确地对齐以下颜色数组。

在搜索并尝试了 Stackoverflow 上建议的许多解决方案之后,pusher.color 库拥有最佳解决方案,但它也远非完美。我想听听有关如何完美对齐它们的解决方案。

JSFIDDLE LINK : http://jsfiddle.net/dxux7y3e/

代码:

var coloursArray=['#FFE9E9','#B85958','#FFB1AE','#FFC2BF','#C55E58','#FFC7C4','#FF9A94','#FF9D96','#FA9790','#A78B88','#A78B88','#CE675B','#DB8073','#FF9D90','#FF7361','#FFD6D1','#F9A092','#FF7B67','#EBACA2','#FF806D','#DD6D5B','#D16654','#ED8673','#FFC4B8','#E2725B','#ED7A64','#8F3926','#BD492F','#9D3C27','#AD533E','#BF4024','#FFC9BC','#6B6766','#E1CDC8','#C2654C','#B3978F','#FFC7B8','#CE2B00','#C2654C','#A24D34','#FF926D','#E78667','#FFB198','#8C756D','#9E6D5B','#FFC7B0','#FFBEA4','#D2B9AF','#FFB193','#632710','#B26746','#976854','#F44900','#E79873','#EFA27F','#532510','#BC866B','#FDE5D9','#FF5B00','#D18C67','#FF5B00','#9E4312','#763713','#BB6B39','#B5622E','#CC7742','#6D4227','#B56B38','#FF7518','#F3B080','#995C30','#995C30','#FF6A00','#D89769','#71472A','#EDAC7B','#EEAB79','#EBCFB9','#FBE3D1','#E19255','#5E381B','#FFDCC1','#FFF0E4','#F68D39','#7B5B40','#FF8313','#FFCEA4','#AA8667','#975414','#CB9867','#8C5B2B','#FFCE9E','#7B4714','#FFF3E7','#FFA449','#CEAF90','#CDB69E','#EFD6BC','#DDA66B','#B27737','#B88A57','#CE9B61','#F4C38B','#543817','#BC9C78','#DBB07A','#FF8E04','#F6EADB','#DBC2A4','#C49B64','#CBA26B','#80551E','#FF9200','#FFECD3','#FFC87C','#FFB755','#DBB680','#D2D0CD','#EFDBBE','#E5C18B','#FFE5BC','#F2EADB','#885F12','#FFE7B6','#825A08','#906712','#F2D18E','#C8C6C2','#FFB000','#FFC243','#C6BEAD','#D0C3A4','#916800','#8C6700','#F4E9CA','#FFF0C5','#FFE080','#FFEBA8','#846600','#FFE692','#F5F0DB','#433F2F','#BBB394','#FFEFAA','#FFE76D','#FFFAE0','#3E3B28','#554900','#E1E0D8','#74725C','#605F54','#F8F7DD','#A5A467','#DDDDDA','#FFFFEE','#A3A39D','#E0E0D7','#BEBEB9','#E8E8E5','#454531','#ACACAA','#E9E9DF','#FFFFDC','#EBEBE7','#979831','#C5C6BE','#B9C866','#898D72','#F3FAD1','#616452','#CED5B0','#A1A787','#595C4E','#B0BB8C','#EEFFB6','#ACB78E','#8FA359','#858F6C','#86916E','#374912','#AEB0AA','#79904C','#627739','#747F60','#9FA98E','#E7F9CB','#E1F9BE','#495637','#8A9978','#4E5F39','#86996E','#C3CEB7','#78866B','#CEDDC1','#B5CEA2','#536149','#D6E6CC','#D6E6CC','#809873','#4F564C','#4F6C45','#555F52','#4F7942','#5F705B','#D0DFCD','#2B3929','#F0F7EF','#AAD5A4','#99BC95','#B6D4B4','#869E86','#618661','#006700','#E9EEE9','#739E73','#005B06','#EDF7EE','#D0E0D2','#809784','#ABCEB1','#C0E0C8','#3A5241','#435549','#E6ECE8','#E3EAE6','#3B604C','#00602F','#92B7A5','#2F5B49','#318061','#30745B','#316955','#00A275','#C2D1CE','#80A7A0','#00A082','#C2D1CF','#5C6E6C','#607473','#EDF7F7','#1E8285','#D5E7E8','#AADEE1','#188086','#107F87','#566364','#007B86','#66949A','#CAE2E5','#18656F','#004F61','#0C5B6C','#668E98','#BBD0DA','#91B4C5','#AFC3CD','#738A99','#3A5467','#476174','#244967','#556C80','#667A8C','#516D87','#1E4263','#7C8791','#849CB6','#738CAA','#1E3A5F','#1E3655','#9EB0CE','#B6BAC2','#67738D','#BEC1CD','#555559','#616180','#000049','#000031','#F8F8FC','#938BA4','#47375D','#F7F6F8','#3D0067','#514C53','#9566A2','#7F5482','#A279A4','#6D1261','#A06492','#925582','#945B80','#CE94BA','#ECCFE1','#A20058','#A6005B','#BC0061','#BB0061','#F3CEE1','#B3005B','#AB165F','#8A184D','#AA185B','#F3DAE4','#DB3779','#E71261','#E74F86','#FFD6E5','#BE9BA7','#D0396A','#DB1855','#F798B6','#9C294A','#D62B5B','#DE3969','#BC1641','#E7547A','#D52756','#9C7D85','#DB244F','#A1354F','#C22443','#FFBDCA','#8B6D73','#DC3D5B','#FF738C','#F13154','#BC4055','#FED4DB','#FFCFD6','#CB4E61','#ED455A','#F36C7B','#C94F5B','#F3959D','#A8444C','#FFCCD0','#735B5D','#D15D67','#B44B52','#FD868D','#FFD5D8','#C3767B','#FF8087','#C8242B','#FFEAEB','#F95A61','#E96D73','#E6656B','#FF6D73','#FF555B','#A35A5B','#FFD3D4','#B84B4D'];
        var body=document.getElementsByTagName('body')[0];

        function hexToRgb(hex) {
            hex = hex.substring(1, hex.length);
            var r = parseInt((hex).substring(0, 2), 16);
            var g = parseInt((hex).substring(2, 4), 16);
            var b = parseInt((hex).substring(4, 6), 16);

            return r + "," + g + "," + b;
        }

        function rgbToHex(r, g, b) {
            return "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
        }

        var rgbArr=new Array();
        var div=document.createElement('div');
        div.id='Original';

        body.appendChild(div);
        for(var color in coloursArray){
            color=coloursArray[color];
            displayColor(color,div); 
            rgbArr.push(hexToRgb(color));
        }

        var hslArr=new Array();
        for(var i=0;i<rgbArr.length;i++){
            //Transforming rgb to hsl
            //`hslArr[i][1]` (`i`) is a reference to the rgb color, in order to retrieve it later
            hslArr[i]=[rgbToHsl(rgbArr[i]),i]; 
        }
        var sortedHslArr=new Array();
        //Sorting `hslArr` into `sortedHslArr`
        outerloop:
            for(var i=0;i<hslArr.length;i++){
            for(var j=0;j<sortedHslArr.length;j++){
                if(sortedHslArr[j][0][0]>hslArr[i][0][0]){
                    sortedHslArr.splice(j,0,hslArr[i]);
                    continue outerloop;
                }
            }
            sortedHslArr.push(hslArr[i]);
        }
        var sortedRgbArr=new Array();
        //Retrieving rgb colors
        for(var i=0;i<sortedHslArr.length;i++){
            sortedRgbArr[i]=rgbArr[sortedHslArr[i][1]];
        }

        function displayColor(color,parent){
            var div;

            div=document.createElement('div');
            div.style.backgroundColor=color;
            div.style.width='22px';
            div.style.height='22px';
            div.style.cssFloat='left';
            div.style.position='relative';
            parent.appendChild(div);
        }

        var finalArray=new Array();
        var div=document.createElement('div');
        div.id='Sorted';
        body.appendChild(div);
        for(var color in sortedRgbArr){
            color=sortedRgbArr[color];
            color=color.split(',');
            color=rgbToHex(parseInt(color[0]),parseInt(color[1]),parseInt(color[2]));                
            displayColor(color,div);                
            finalArray.push(color);
        }

        function rgbToHsl(c){
            var r = c[0]/255, g = c[1]/255, b = c[2]/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 new Array(h * 360, s * 100, l * 100);
        } 

        var sorted = coloursArray.sort(function(colorA, colorB) {
            return pusher.color(colorA).hue() - pusher.color(colorB).hue();
        });
      //  console.log(sorted);

        var div=document.createElement('div');
        div.id='Pusher';
        body.appendChild(div);
        for(var color in sorted){
            color=sorted[color];                               
            displayColor(color,div);    
        }            

        var div=document.createElement('div');            
        body.appendChild(div);
        var str='';
        for(var color in sorted){
            color=sorted[color];                              
            str+='\''+color+'\',';
        } 
        div.innerHTML=str;


        function sorthueColors (colors) {
            for (var c = 0; c < colors.length; c++) {
                /* Get the hex value without hash symbol. */
                var hex = colors[c].substring(1);
                //var hex = colors[c].hex.substring(1);

                /* Get the RGB values to calculate the Hue. */
                var r = parseInt(hex.substring(0,2),16)/255;
                var g = parseInt(hex.substring(2,4),16)/255;
                var b = parseInt(hex.substring(4,6),16)/255;

                /* Getting the Max and Min values for Chroma. */
                var max = Math.max.apply(Math, [r,g,b]);
                var min = Math.min.apply(Math, [r,g,b]);

                /* Variables for HSV value of hex color. */
                var chr = max-min;
                var hue = 0;
                var val = max;
                var sat = 0;

                if (val > 0) {
                    /* Calculate Saturation only if Value isn't 0. */
                    sat = chr/val;
                    if (sat > 0) {
                        if (r == max) { 
                            hue = 60*(((g-min)-(b-min))/chr);
                            if (hue < 0) {hue += 360;}
                        } else if (g == max) { 
                            hue = 120+60*(((b-min)-(r-min))/chr); 
                        } else if (b == max) { 
                            hue = 240+60*(((r-min)-(g-min))/chr); 
                        }
                    }
                }

                /* Modifies existing objects by adding HSV values. */
                colors[c].hue = hue;
                colors[c].sat = sat;
                colors[c].val = val;
            }

            /* Sort by Hue. */
            return colors.sort(function(a,b){return a.hue - b.hue;});
        }

最佳答案

问题是,排序需要明确定义的顺序 - 换句话说,您需要将所有颜色映射到一个维度。虽然有一些方法可以在二维中显示颜色空间,但我不知道有任何方法可以在一维中显示它并且对人眼仍然有意义。

但是,如果您不坚持某种通用排序,而只想以一种看起来不错的方式放置给定的颜色列表,那么某些聚类方法可能会产生更好的结果。我尝试了天真的方法,这里的想法是将相似的颜色放入同一个簇中并合并这些簇,直到你只有一个。这是我得到的代码:

function colorDistance(color1, color2) {
    // This is actually the square of the distance but
    // this doesn't matter for sorting.
    var result = 0;
    for (var i = 0; i < color1.length; i++)
        result += (color1[i] - color2[i]) * (color1[i] - color2[i]);
    return result;
}

function sortColors(colors) {
    // Calculate distance between each color
    var distances = [];
    for (var i = 0; i < colors.length; i++) {
        distances[i] = [];
        for (var j = 0; j < i; j++)
            distances.push([colors[i], colors[j], colorDistance(colors[i], colors[j])]);
    }
    distances.sort(function(a, b) {
        return a[2] - b[2];
    });

    // Put each color into separate cluster initially
    var colorToCluster = {};
    for (var i = 0; i < colors.length; i++)
        colorToCluster[colors[i]] = [colors[i]];

    // Merge clusters, starting with lowest distances
    var lastCluster;
    for (var i = 0; i < distances.length; i++) {
        var color1 = distances[i][0];
        var color2 = distances[i][1];
        var cluster1 = colorToCluster[color1];
        var cluster2 = colorToCluster[color2];
        if (!cluster1 || !cluster2 || cluster1 == cluster2)
            continue;

        // Make sure color1 is at the end of its cluster and
        // color2 at the beginning.
        if (color1 != cluster1[cluster1.length - 1])
            cluster1.reverse();
        if (color2 != cluster2[0])
            cluster2.reverse();

        // Merge cluster2 into cluster1
        cluster1.push.apply(cluster1, cluster2);
        delete colorToCluster[color1];
        delete colorToCluster[color2];
        colorToCluster[cluster1[0]] = cluster1;
        colorToCluster[cluster1[cluster1.length - 1]] = cluster1;
        lastCluster = cluster1;
    }

    // By now all colors should be in one cluster
    return lastCluster;
}

Complete fiddle

colorDistance() 函数处理 RGB 颜色,这些颜色表示为包含三个元素的数组。肯定有much better approaches to do this他们可能会产生看起来更好的结果。另请注意,这不是最有效的算法,因为它会计算每种颜色之间的距离 (O(n2)),因此如果您有很多颜色,您可能需要对其进行优化。

关于javascript - 排序颜色/颜色值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25822124/

相关文章:

javascript - JS & Node : Read table from DB with AJAX and display in table

java - 意外地重新定义迭代器中的变量以读取所有列表元素

javascript - 在不使用任何内置方法的情况下在javascript中按降序对数组进行排序

algorithm - 如何在 Ada 中进行快速排序

php - 在自定义 foreach 循环中按字母顺序对结果进行排序

javascript - 展开 Fabric.js 中的 stateProperties

javascript - Jquery平滑滚动(非锚定)

javascript - 将异步函数的结果分配给同步函数中的变量

python - 如何省略数组中的某些值

java - 嵌套循环的顺序对速度有影响吗