views:

39

answers:

3

In my app i want the users to select a base colour for elements to be displayed on a calendar. From the base colour the user has selected, i need to be able to automatically set an appropriate border colour, and an appropriate text colour.

When i mean appropriate i mean a darker tint or shade variation for the border

Are there any jquery plugins that do this already, or indeed any other plugins for another javascript library?

If not can people offer advice about how to go about doing the calculations? I've not got much experience in colour theory.

Thank you.

+2  A: 

you can try this:

http://www.javascriptrules.com/2009/08/05/css-color-brightness-contrast-using-javascript/

or u can try this snippet:

function lighten(color, factor) {
    factor = factor || 0.4;
    var lighter = '#';
    for(var i = 1; i < 6; i += 2) {
        var part = parseInt(color.substr(i, 2), 16);
        part += Math.round((255 - part) * 0.4);
        lighter += (part < 16 ? '0' : '') + part.toString(16);
    }
    return lighter;
}
lighten('#ececec'); // returns '#f4f4f4'

or use this snippet:

function LightenColor(rgbtext, delta) {
      var r, g, b, txt;
      r= parseInt(rgbtext.substr(1, 2), 16),
      g= parseInt(rgbtext.substr(3, 2), 16),
      b= parseInt(rgbtext.substr(5, 2), 16),

      r+= delta;  if (r> 255) r= 255;  if (r< 0) r= 0;
      g+= delta;  if (g> 255) g= 255;  if (g< 0) g= 0;
      b+= delta;  if (b> 255) b= 255;  if (b< 0) b= 0;
      txt= b.toString(16);       if (txt.length< 2) txt= "0"+ txt;
      txt= g.toString(16)+ txt;  if (txt.length< 4) txt= "0"+ txt;
      txt= r.toString(16)+ txt;  if (txt.length< 6) txt= "0"+ txt;

      return "#"+ txt;
    }
    function DarkenColor(rgbtext, delta) {
      return LightenColor(rgbtext, delta* -1);
    }
LightenColor('#AF0000', 50);
DarkenColor('#AF0000', 50);
Vaibhav Gupta
+1 for cool algorithm.
Stephen
thanks, i'm aware of the algorithm that allocates a black or white text color, but i'm after something that will give a different tint or shade variation to the base color.
Doozer1979
Great stuff! i'll give it a whirl.
Doozer1979
+1  A: 

I don't have a specific code sample on hand for something like this but here's an idea on how to do it with math. Set 0 - 9 to their value and A - F to 10 - 15, like below (you will also need to multiple these values by 16, will make sense in a second):

0 : 0 : 0
1 : 1 : 16
2 : 2 : 32
...
A : 10 : 160
B : 11 : 176
C : 12 : 192
...
F : 15 : 240

Once you have this set up you can (assuming your color is in HEX) separate the 3 groupings and convert each to their hexadecimal equivalent. The first character of the two is multiplied by 16 and the 2nd is multiplied by 1:

FF = (16 * 15) + (15 * 1) = 255
AE = (16 * 10) + (14 * 1) = 174
0F = (16 * 0 ) + (15 * 1) = 15

Once you have the hexadecimal numbers for the color the user picks you can multiple each hexadecimal number based on a formula.

Below is an example, I'm using a lighter red and I want to find a darker red. My starting HEX is DB4658 and I'm going to multiple my values by .5 to get my darker red:

  1. Separate into 3 groups: DB 46 58
  2. Calculate the Hexadecimal value of each:

      D = 13   B = 11   4 = 4   6 = 6   5 = 5   8 = 8
      DB = 219 = 13 * 16 + 11 * 1
      46 = 70 = 4 * 16 + 6 * 1
      58 = 88 = 5 * 16 + 8 * 1
    
  3. Now calculating those into the darker HEX (I floored the number):

      219 * .5 = 109
      70 * .5 = 35
      88 * .5 = 44
    
  4. Convert this back into our 3 Groupings, for the first character look at your table you have built in the multiply by 16 column:

      109 = 96 + 13 = 6D
      35 = 32 + 3 = 23
      44 = 32 + 12 = 2C
    
  5. You now have your darker red.

You might adjust the .5 to .75 if you want the contrast closer together and if the color they pick is already dark then the adjustment should be by 1.25x or 1.5x.

Hopefully you find this helpful. If you need clarification let me know.

cmullins
Really good answer, and you've broadened my knowledge, thank you very much.
Doozer1979
+2  A: 

You can think of a color like a 3D vector with black in a corner and white in the exact oposite:

function color_to_vector(color) {
    return {
        r : parseInt(color.substr(1, 2), 16),
        g : parseInt(color.substr(3, 2), 16),
        b : parseInt(color.substr(5, 2), 16)
    }
}

function vector_to_color(vector){
    return "#"+
        (vector.r < 16 ? '0' : '') + vector.r.toString(16)+
        (vector.g < 16 ? '0' : '') + vector.g.toString(16)+
        (vector.b < 16 ? '0' : '') + vector.b.toString(16);
}

So, do you wanna a darker color? Then:

function darker(color){
    var vector = color_to_vector(color);
    vector.r /= 2;
    vector.g /= 2;
    vector.b /= 2;
    return vector_to_color(vector);
}

A lighter one?

function lighter(color){
    var vector = color_to_vector(color);
    vector.r += (255 - vector.r) / 2;
    vector.g += (255 - vector.g) / 2;
    vector.b += (255 - vector.b) / 2;
    return vector_to_color(vector);
}

A "blueish" one?

function lighter(color){
    var vector = color_to_vector(color);
    vector.b += (255 - vector.b) / 2;
    return vector_to_color(vector);
}

And so.

Erik Escobedo
Thank you very much, i've had some really good answers from this question, it's a shame you can only tick one!
Doozer1979