生成随机颜色偏差

3
我希望能用JavaScript生成与给定颜色稍有不同的随机颜色。例如,假设我有一个颜色#33CCFF,我想将该数字输入脚本并得到像#8AE2FF#00AAE2#7BDEFF这样的数字。基本上,色调应保持不变,但饱和度/亮度应稍微波动。

生成这些数字的最快最简单的方法是什么?


3
如果您正在使用现代浏览器,实际上可以使用HSL来指定颜色,而不是使用十六进制代码。这将使您的任务变得非常简单。http://www.css3.info/preview/hsl/ - Brian Glaz
@BrianGlaz:这是一个不错的小技巧,但不幸的是,我正在努力保持浏览器兼容性,即使是IE。 - Alexis King
3个回答

4

0
说实话,我不知道十六进制代码如何计算饱和度/亮度,所以我会转换为HSL:

http://serennu.com/colour/rgbtohsl.php

修改您想要的内容,再将其改回来。我唯一看到的主要缺点是,在更改后,HSL可能不会存在于十六进制字段中。

例如,

HSL颜色空间只有360 x 100 x 100 = 3,600,000种颜色,而RGB颜色空间有256 x 256 x 256 = 16,77,216种颜色,这是前者的四倍多。


0

我知道这个问题已经一年了,但是我在寻找解决方案时找不到。

但是基于一些建议(主要来自SO),我创建了一个可用的脚本。

注意1:colorToRGB函数不可靠。我在SO(源代码附带)中找到了它。我更改了一些颜色的十六进制值,但我不想检查所有颜色的结果。为了获得最佳结果,请始终使用十六进制值。

注意2:在generateSimilarColor函数中,deviation仅设置了我的目的。您可以更改它以获得更好的结果。

注意3:许多函数都在SO上找到。我只是把它们聚集在一起,并提供相应问题的链接。

以下是JavaScript代码(在帖子底部进行测试环境):

/**
* Generates similar color based on passed one
* 
* @param color accepts few formats, e.g. white, #ffffff or [255, 255, 255]
* @return hex value, e.g. #ffffff
* 
* @author Carlos (StackOverflow)
*/
function generateSimilarColor(color) {

   var rand = generateRandomInt(-5, 5);
   if(rand < 0) rand -= 5;
   else rand += 5;
   var deviation = rand / 100;

   if(!isArray(color) || color.length != 3) { // this is not [r, g, b] array

       var hexNotation = colorToRGB(color);

       if(!hexNotation) { // we couldn't find HEX value of this string based on color name
           if(!isString(color) || color.length != 7 || color[0] != '#') { // this is not string in this format: #ffffff
               return false;
           }
           else {
               hexNotation = color;
           }
       }

       color = hexToRgb(hexNotation);

       if(!color) {
           return false;
       }
   }

   var hsl = rgbToHsl(color[0], color[1], color[2]);

   // saturation
   hsl[1] += deviation;
   if(hsl[1] > 1) hsl[1] = 1 - Math.abs(deviation);
   else if(hsl[1] < 0) hsl[1] = Math.abs(deviation);

   // lightness
   hsl[2] += deviation;
   if(hsl[2] > 1) hsl[2] = 1 - Math.abs(deviation);
   else if(hsl[2] < 0) hsl[2] = Math.abs(deviation);

   color = hslToRgb(hsl[0], hsl[1], hsl[2]);
   var hex = rgbToHex(color[0], color[1], color[2]);

   return hex;
}

/**
* Returns a random integer between min and max
* Using Math.round() will give you a non-uniform distribution!
* 
* @source https://dev59.com/-nI_5IYBdhLWcg3wF_B3
*/
function generateRandomInt(min, max) {
    return Math.floor(Math.random() * (max - min + 1)) + min;
}

/**
 * @source: [slightly changed] https://dev59.com/7G035IYBdhLWcg3wGMDa
 */
function componentToHex(c) {
    var hex = c.toString(16);
    return hex.length == 1 ? "0" + hex : hex;
}

/**
 * @source: [slightly changed] https://dev59.com/7G035IYBdhLWcg3wGMDa
 */
function rgbToHex(r, g, b) {
    r = parseInt(r);
    g = parseInt(g);
    b = parseInt(b);
    return "#" + componentToHex(r) + componentToHex(g) + componentToHex(b);
}

/**
* @source https://dev59.com/I3NA5IYBdhLWcg3wL6yx
*/
function isArray(obj) {
    return Object.prototype.toString.call(obj) === '[object Array]';
}

/**
* @source https://dev59.com/HW855IYBdhLWcg3w-JQr
*/
function isString(str) {
    return (typeof str == 'string' || str instanceof String);
}

/**
* @source: https://dev59.com/7G035IYBdhLWcg3wGMDa slightly change
*/
function hexToRgb(hex) {

   // Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF")
   var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
   hex = hex.replace(shorthandRegex, function(m, r, g, b) {
       return r + r + g + g + b + b;
   });

   var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
   return result ? [
       parseInt(result[1], 16),
       parseInt(result[2], 16),
       parseInt(result[3], 16)
   ] : false;
}

/**
* Converts an RGB color value to HSL. Conversion formula
* adapted from http://en.wikipedia.org/wiki/HSL_color_space.
* Assumes r, g, and b are contained in the set [0, 255] and
* returns h, s, and l in the set [0, 1].
*
* @param   Number  r       The red color value
* @param   Number  g       The green color value
* @param   Number  b       The blue color value
* @return  Array           The HSL representation
* 
* @source http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript
*/
function rgbToHsl(r, g, b) {
   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];
}

/**
* Converts an HSL color value to RGB. Conversion formula
* adapted from http://en.wikipedia.org/wiki/HSL_color_space.
* Assumes h, s, and l are contained in the set [0, 1] and
* returns r, g, and b in the set [0, 255].
*
* @param   Number  h       The hue
* @param   Number  s       The saturation
* @param   Number  l       The lightness
* @return  Array           The RGB representation
*/
function hslToRgb(h, s, l) {
   var r, g, b;

   if(s == 0){
       r = g = b = l; // achromatic
   }else{
       function hue2rgb(p, q, t){
           if(t < 0) t += 1;
           if(t > 1) t -= 1;
           if(t < 1/6) return p + (q - p) * 6 * t;
           if(t < 1/2) return q;
           if(t < 2/3) return p + (q - p) * (2/3 - t) * 6;
           return p;
       }

       var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
       var p = 2 * l - q;
       r = hue2rgb(p, q, h + 1/3);
       g = hue2rgb(p, q, h);
       b = hue2rgb(p, q, h - 1/3);
   }

   return [r * 255, g * 255, b * 255];
}

/**
* @source [slightly changed] https://dev59.com/23I_5IYBdhLWcg3wAd82
*/
function colorToRGB(color) {

    var colors = {"aliceblue":"#f0f8ff","antiquewhite":"#faebd7","aqua":"#00ffff","aquamarine":"#7fffd4","azure":"#f0ffff",
    "beige":"#f5f5dc","bisque":"#ffe4c4","black":"#000000","blanchedalmond":"#ffebcd","blue":"#0000ff","blueviolet":"#8a2be2","brown":"#603311","burlywood":"#deb887",
    "cadetblue":"#5f9ea0","chartreuse":"#7fff00","chocolate":"#d2691e","coral":"#ff7f50","cornflowerblue":"#6495ed","cornsilk":"#fff8dc","crimson":"#dc143c","cyan":"#00ffff",
    "darkblue":"#00008b","darkcyan":"#008b8b","darkgoldenrod":"#b8860b","darkgray":"#a9a9a9","darkgreen":"#006400","darkkhaki":"#bdb76b","darkmagenta":"#8b008b","darkolivegreen":"#556b2f",
    "darkorange":"#ff8c00","darkorchid":"#9932cc","darkred":"#8b0000","darksalmon":"#e9967a","darkseagreen":"#8fbc8f","darkslateblue":"#483d8b","darkslategray":"#2f4f4f","darkturquoise":"#00ced1",
    "darkviolet":"#9400d3","deeppink":"#ff1493","deepskyblue":"#00bfff","dimgray":"#696969","dodgerblue":"#1e90ff",
    "firebrick":"#b22222","floralwhite":"#fffaf0","forestgreen":"#228b22","fuchsia":"#ff00ff",
    "gainsboro":"#dcdcdc","ghostwhite":"#f8f8ff","gold":"#ffd700","goldenrod":"#daa520","gray":"#808080","green":"#008000","greenyellow":"#adff2f",
    "honeydew":"#f0fff0","hotpink":"#ff69b4",
    "indianred ":"#cd5c5c","indigo ":"#4b0082","ivory":"#fffff0","khaki":"#f0e68c",
    "lavender":"#e6e6fa","lavenderblush":"#fff0f5","lawngreen":"#7cfc00","lemonchiffon":"#fffacd","lightblue":"#add8e6","lightcoral":"#f08080","lightcyan":"#e0ffff","lightgoldenrodyellow":"#fafad2",
    "lightgrey":"#d3d3d3","lightgreen":"#90ee90","lightpink":"#ffb6c1","lightsalmon":"#ffa07a","lightseagreen":"#20b2aa","lightskyblue":"#87cefa","lightslategray":"#778899","lightsteelblue":"#b0c4de",
    "lightyellow":"#ffffe0","lime":"#00ff00","limegreen":"#32cd32","linen":"#faf0e6",
    "magenta":"#ff00ff","maroon":"#800000","mediumaquamarine":"#66cdaa","mediumblue":"#0000cd","mediumorchid":"#ba55d3","mediumpurple":"#9370d8","mediumseagreen":"#3cb371","mediumslateblue":"#7b68ee",
    "mediumspringgreen":"#00fa9a","mediumturquoise":"#48d1cc","mediumvioletred":"#c71585","midnightblue":"#191970","mintcream":"#f5fffa","mistyrose":"#ffe4e1","moccasin":"#ffe4b5",
    "navajowhite":"#ffdead","navy":"#000080",
    "oldlace":"#fdf5e6","olive":"#808000","olivedrab":"#6b8e23","orange":"#ffa500","orangered":"#ff4500","orchid":"#da70d6",
    "palegoldenrod":"#eee8aa","palegreen":"#98fb98","paleturquoise":"#afeeee","palevioletred":"#d87093","papayawhip":"#ffefd5","peachpuff":"#ffdab9","peru":"#cd853f","pink":"#ffc0cb","plum":"#dda0dd","powderblue":"#b0e0e6","purple":"#800080",
    "red":"#ff0000","rosybrown":"#bc8f8f","royalblue":"#4169e1",
    "saddlebrown":"#8b4513","salmon":"#fa8072","sandybrown":"#f4a460","seagreen":"#2e8b57","seashell":"#fff5ee","sienna":"#a0522d","silver":"#c0c0c0","skyblue":"#87ceeb","slateblue":"#6a5acd","slategray":"#708090","snow":"#fffafa","springgreen":"#00ff7f","steelblue":"#4682b4",
    "tan":"#d2b48c","teal":"#008080","thistle":"#d8bfd8","tomato":"#ff6347","turquoise":"#40e0d0",
    "violet":"#8F00FF",
    "wheat":"#f5deb3","white":"#ffffff","whitesmoke":"#f5f5f5",
    "yellow":"#ffff00","yellowgreen":"#9acd32"};

    if (typeof colors[color.toLowerCase()] != 'undefined')
        return colors[color.toLowerCase()];

    return false;
}

测试环境(需要 jQuery):

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <meta charset="utf-8">
        <title>Color Test</title>
        <script type="text/javascript" src="js/libs/jquery.js"></script>
        <script type="text/javascript" src="js/color.js"></script>
        <script type="text/javascript">
            $(document).ready(function() {
                var i, j, colors = ['blue', 'orange', 'green', 'red', 'yellow', 'brown', 'violet'];
                for(i = 0; i < colors.length; i++) {
                    for(j = 0; j < 3; j++) {
                        $("body").append('<div style="height: 20px; background-color: ' + generateSimilarColor(colors[i]) + ';"></div>');
                    }
                    $("body").append('<div style="height: 20px;"></div>');
                }
            });
        </script>
    </head>
    <body></body>
</html>

如有任何漏洞或建议,请写下来。


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