annot-server/static/js/randomColor.js
changeset 83 9be99c2fb279
parent 82 ae37d35a419c
child 84 d7c5bffdd2d8
equal deleted inserted replaced
82:ae37d35a419c 83:9be99c2fb279
     1 ;(function(root, factory) {
       
     2 
       
     3   // Support AMD
       
     4   if (typeof define === 'function' && define.amd) {
       
     5     define([], factory);
       
     6 
       
     7   // Support CommonJS
       
     8   } else if (typeof exports === 'object') {
       
     9     var randomColor = factory();
       
    10     
       
    11     // Support NodeJS & Component, which allow module.exports to be a function
       
    12     if (typeof module === 'object' && module && module.exports) {
       
    13       exports = module.exports = randomColor;
       
    14     }
       
    15     
       
    16     // Support CommonJS 1.1.1 spec
       
    17     exports.randomColor = randomColor;
       
    18   
       
    19   // Support vanilla script loading
       
    20   } else {
       
    21     root.randomColor = factory();
       
    22   };
       
    23 
       
    24 }(this, function() {
       
    25 
       
    26   // Shared color dictionary
       
    27   var colorDictionary = {};
       
    28 
       
    29   // Populate the color dictionary
       
    30   loadColorBounds();
       
    31 
       
    32   var randomColor = function(options) {
       
    33     options = options || {};
       
    34 
       
    35     var H,S,B;
       
    36 
       
    37     // Check if we need to generate multiple colors
       
    38     if (options.count) {
       
    39 
       
    40       var totalColors = options.count,
       
    41           colors = [];
       
    42 
       
    43       options.count = false;
       
    44 
       
    45       while (totalColors > colors.length) {
       
    46         colors.push(randomColor(options));
       
    47       }
       
    48 
       
    49       return colors;
       
    50     }
       
    51 
       
    52     // First we pick a hue (H)
       
    53     H = pickHue(options);
       
    54 
       
    55     // Then use H to determine saturation (S)
       
    56     S = pickSaturation(H, options);
       
    57 
       
    58     // Then use S and H to determine brightness (B).
       
    59     B = pickBrightness(H, S, options);
       
    60 
       
    61     // Then we return the HSB color in the desired format
       
    62     return setFormat([H,S,B], options);
       
    63   };
       
    64 
       
    65   function pickHue (options) {
       
    66 
       
    67     var hueRange = getHueRange(options.hue),
       
    68         hue = randomWithin(hueRange);
       
    69 
       
    70     // Instead of storing red as two seperate ranges,
       
    71     // we group them, using negative numbers
       
    72     if (hue < 0) {hue = 360 + hue}
       
    73 
       
    74     return hue;
       
    75 
       
    76   }
       
    77 
       
    78   function pickSaturation (hue, options) {
       
    79 
       
    80     if (options.luminosity === 'random') {
       
    81       return randomWithin([0,100]);
       
    82     }
       
    83 
       
    84     if (options.hue === 'monochrome') {
       
    85       return 0;
       
    86     }
       
    87 
       
    88     var saturationRange = getSaturationRange(hue);
       
    89 
       
    90     var sMin = saturationRange[0],
       
    91         sMax = saturationRange[1];
       
    92 
       
    93     switch (options.luminosity) {
       
    94 
       
    95       case 'bright':
       
    96         sMin = 55;
       
    97         break;
       
    98 
       
    99       case 'dark':
       
   100         sMin = sMax - 10;
       
   101         break;
       
   102 
       
   103       case 'light':
       
   104         sMax = 55;
       
   105         break;
       
   106    }
       
   107 
       
   108     return randomWithin([sMin, sMax]);
       
   109 
       
   110   }
       
   111 
       
   112   function pickBrightness (H, S, options) {
       
   113 
       
   114     var brightness,
       
   115         bMin = getMinimumBrightness(H, S),
       
   116         bMax = 100;
       
   117 
       
   118     switch (options.luminosity) {
       
   119 
       
   120       case 'dark':
       
   121         bMax = bMin + 20;
       
   122         break;
       
   123 
       
   124       case 'light':
       
   125         bMin = (bMax + bMin)/2;
       
   126         break;
       
   127 
       
   128       case 'random':
       
   129         bMin = 0;
       
   130         bMax = 100;
       
   131         break;
       
   132     }
       
   133 
       
   134     return randomWithin([bMin, bMax]);
       
   135 
       
   136   }
       
   137 
       
   138   function setFormat (hsv, options) {
       
   139 
       
   140     switch (options.format) {
       
   141 
       
   142       case 'hsvArray':
       
   143         return hsv;
       
   144 
       
   145       case 'hsv':
       
   146         return colorString('hsv', hsv);
       
   147 
       
   148       case 'rgbArray':
       
   149         return HSVtoRGB(hsv);
       
   150 
       
   151       case 'rgb':
       
   152         return colorString('rgb', HSVtoRGB(hsv));
       
   153 
       
   154       default:
       
   155         return HSVtoHex(hsv);
       
   156     }
       
   157 
       
   158   }
       
   159 
       
   160   function getMinimumBrightness(H, S) {
       
   161 
       
   162     var lowerBounds = getColorInfo(H).lowerBounds;
       
   163 
       
   164     for (var i = 0; i < lowerBounds.length - 1; i++) {
       
   165 
       
   166       var s1 = lowerBounds[i][0],
       
   167           v1 = lowerBounds[i][1];
       
   168 
       
   169       var s2 = lowerBounds[i+1][0],
       
   170           v2 = lowerBounds[i+1][1];
       
   171 
       
   172       if (S >= s1 && S <= s2) {
       
   173 
       
   174          var m = (v2 - v1)/(s2 - s1),
       
   175              b = v1 - m*s1;
       
   176 
       
   177          return m*S + b;
       
   178       }
       
   179 
       
   180     }
       
   181 
       
   182     return 0;
       
   183   }
       
   184 
       
   185   function getHueRange (colorInput) {
       
   186 
       
   187     if (typeof parseInt(colorInput) === 'number') {
       
   188 
       
   189       var number = parseInt(colorInput);
       
   190 
       
   191       if (number < 360 && number > 0) {
       
   192         return [number, number];
       
   193       }
       
   194 
       
   195     }
       
   196 
       
   197     if (typeof colorInput === 'string') {
       
   198 
       
   199       if (colorDictionary[colorInput]) {
       
   200         var color = colorDictionary[colorInput];
       
   201         if (color.hueRange) {return color.hueRange}
       
   202       }
       
   203     }
       
   204 
       
   205     return [0,360];
       
   206 
       
   207   }
       
   208 
       
   209   function getSaturationRange (hue) {
       
   210     return getColorInfo(hue).saturationRange;
       
   211   }
       
   212 
       
   213   function getColorInfo (hue) {
       
   214 
       
   215     // Maps red colors to make picking hue easier
       
   216     if (hue >= 334 && hue <= 360) {
       
   217       hue-= 360;
       
   218     }
       
   219 
       
   220     for (var colorName in colorDictionary) {
       
   221        var color = colorDictionary[colorName];
       
   222        if (color.hueRange &&
       
   223            hue >= color.hueRange[0] &&
       
   224            hue <= color.hueRange[1]) {
       
   225           return colorDictionary[colorName];
       
   226        }
       
   227     } return 'Color not found';
       
   228   }
       
   229 
       
   230   function randomWithin (range) {
       
   231     return Math.floor(range[0] + Math.random()*(range[1] + 1 - range[0]));
       
   232   }
       
   233 
       
   234   function shiftHue (h, degrees) {
       
   235     return (h + degrees)%360;
       
   236   }
       
   237 
       
   238   function HSVtoHex (hsv){
       
   239 
       
   240     var rgb = HSVtoRGB(hsv);
       
   241 
       
   242     function componentToHex(c) {
       
   243         var hex = c.toString(16);
       
   244         return hex.length == 1 ? "0" + hex : hex;
       
   245     }
       
   246 
       
   247     var hex = "#" + componentToHex(rgb[0]) + componentToHex(rgb[1]) + componentToHex(rgb[2]);
       
   248 
       
   249     return hex;
       
   250 
       
   251   }
       
   252 
       
   253   function defineColor (name, hueRange, lowerBounds) {
       
   254 
       
   255     var sMin = lowerBounds[0][0],
       
   256         sMax = lowerBounds[lowerBounds.length - 1][0],
       
   257 
       
   258         bMin = lowerBounds[lowerBounds.length - 1][1],
       
   259         bMax = lowerBounds[0][1];
       
   260 
       
   261     colorDictionary[name] = {
       
   262       hueRange: hueRange,
       
   263       lowerBounds: lowerBounds,
       
   264       saturationRange: [sMin, sMax],
       
   265       brightnessRange: [bMin, bMax]
       
   266     };
       
   267 
       
   268   }
       
   269 
       
   270   function loadColorBounds () {
       
   271 
       
   272     defineColor(
       
   273       'monochrome',
       
   274       null,
       
   275       [[0,0],[100,0]]
       
   276     );
       
   277 
       
   278     defineColor(
       
   279       'red',
       
   280       [-26,18],
       
   281       [[20,100],[30,92],[40,89],[50,85],[60,78],[70,70],[80,60],[90,55],[100,50]]
       
   282     );
       
   283 
       
   284     defineColor(
       
   285       'orange',
       
   286       [19,46],
       
   287       [[20,100],[30,93],[40,88],[50,86],[60,85],[70,70],[100,70]]
       
   288     );
       
   289 
       
   290     defineColor(
       
   291       'yellow',
       
   292       [47,62],
       
   293       [[25,100],[40,94],[50,89],[60,86],[70,84],[80,82],[90,80],[100,75]]
       
   294     );
       
   295 
       
   296     defineColor(
       
   297       'green',
       
   298       [63,158],
       
   299       [[30,100],[40,90],[50,85],[60,81],[70,74],[80,64],[90,50],[100,40]]
       
   300     );
       
   301 
       
   302     defineColor(
       
   303       'blue',
       
   304       [159, 257],
       
   305       [[20,100],[30,86],[40,80],[50,74],[60,60],[70,52],[80,44],[90,39],[100,35]]
       
   306     );
       
   307 
       
   308     defineColor(
       
   309       'purple',
       
   310       [258, 282],
       
   311       [[20,100],[30,87],[40,79],[50,70],[60,65],[70,59],[80,52],[90,45],[100,42]]
       
   312     );
       
   313 
       
   314     defineColor(
       
   315       'pink',
       
   316       [283, 334],
       
   317       [[20,100],[30,90],[40,86],[60,84],[80,80],[90,75],[100,73]]
       
   318     );
       
   319 
       
   320   }
       
   321 
       
   322   function HSVtoRGB (hsv) {
       
   323 
       
   324     // this doesn't work for the values of 0 and 360
       
   325     // here's the hacky fix
       
   326     var h = hsv[0];
       
   327     if (h === 0) {h = 1}
       
   328     if (h === 360) {h = 359}
       
   329 
       
   330     // Rebase the h,s,v values
       
   331     h = h/360;
       
   332     var s = hsv[1]/100,
       
   333         v = hsv[2]/100;
       
   334 
       
   335     var h_i = Math.floor(h*6),
       
   336       f = h * 6 - h_i,
       
   337       p = v * (1 - s),
       
   338       q = v * (1 - f*s),
       
   339       t = v * (1 - (1 - f)*s),
       
   340       r = 256,
       
   341       g = 256,
       
   342       b = 256;
       
   343 
       
   344     switch(h_i) {
       
   345       case 0: r = v, g = t, b = p;  break;
       
   346       case 1: r = q, g = v, b = p;  break;
       
   347       case 2: r = p, g = v, b = t;  break;
       
   348       case 3: r = p, g = q, b = v;  break;
       
   349       case 4: r = t, g = p, b = v;  break;
       
   350       case 5: r = v, g = p, b = q;  break;
       
   351     }
       
   352     var result = [Math.floor(r*255), Math.floor(g*255), Math.floor(b*255)];
       
   353     return result;
       
   354   }
       
   355 
       
   356   function colorString (prefix, values) {
       
   357     return prefix + '(' + values.join(', ') + ')';
       
   358   }
       
   359 
       
   360   return randomColor;
       
   361 }));