生成随机颜色偏差

时间:2012-01-25 21:42:51

标签: javascript random colors generator

我想采用一种颜色,并使用JavaScript生成与该颜色的随机偏差。例如,假设我有一个颜色#33CCFF,我想将该数字输入到脚本中,并获得#8AE2FF#00AAE2#7BDEFF等数字。基本上,色调应保持不变,但饱和度/亮度应略有波动。

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

3 个答案:

答案 0 :(得分:4)

将RGB颜色转换为HSL,保持色调,使用一个小的随机数导出饱和度和亮度(亮度),然后转换回RGB。

转换:http://en.wikipedia.org/wiki/HSL_and_HSV#From_HSL

奖金,转换代码:http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript

答案 1 :(得分:0)

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

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

更改您想要的内容,然后将其更改回来。我看到的唯一主要缺点是在您更改HSL后,HSL不存在于Hex字段中。

如同,

  

HSL色彩空间仅为360 x 100 x 100 = 3,600,000   其中的颜色,而RGB颜色空间有256 x 256 x 256 =   其中有16,77,216种颜色,这是其中的四倍。

答案 2 :(得分:0)

我知道这个问题已经有一年了,但是我一直在寻找解决方案而无法找到它。

但是基于这里和那里的建议(主要是关于SO),我创建了可以使用的脚本。

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

注意2:deviation函数中的generateSimilarColor仅用于我的目的。您可以更改它以获得更好的结果。

注意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 http://stackoverflow.com/questions/1527803/generating-random-numbers-in-javascript-in-a-specific-range
*/
function generateRandomInt(min, max) {
    return Math.floor(Math.random() * (max - min + 1)) + min;
}

/**
 * @source: [slightly changed] http://stackoverflow.com/questions/5623838/rgb-to-hex-and-hex-to-rgb
 */
function componentToHex(c) {
    var hex = c.toString(16);
    return hex.length == 1 ? "0" + hex : hex;
}

/**
 * @source: [slightly changed] http://stackoverflow.com/questions/5623838/rgb-to-hex-and-hex-to-rgb
 */
function rgbToHex(r, g, b) {
    r = parseInt(r);
    g = parseInt(g);
    b = parseInt(b);
    return "#" + componentToHex(r) + componentToHex(g) + componentToHex(b);
}

/**
* @source http://stackoverflow.com/questions/1058427/how-to-detect-if-a-variable-is-an-array
*/
function isArray(obj) {
    return Object.prototype.toString.call(obj) === '[object Array]';
}

/**
* @source http://stackoverflow.com/questions/4059147/check-if-a-variable-is-a-string
*/
function isString(str) {
    return (typeof str == 'string' || str instanceof String);
}

/**
* @source: http://stackoverflow.com/questions/5623838/rgb-to-hex-and-hex-to-rgb 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] http://stackoverflow.com/questions/1573053/javascript-function-to-convert-color-names-to-hex-codes
*/
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>

任何错误或建议 - 请写下来。