Question

This problem popped up when I looked at an almost perfect bit of jQuery code called Jar Two Wheel Color Picker:

http://www.jar2.net/projects/jquery-wheelcolorpicker/demo

If you notice in their demo when you move your cursor over the wheel, the developer appears to be using an inverse color algorithm that's slightly imperfect. I mean, if you use it and paste in 8072ff, you end up with something you can't read in the textbox.

The fix in my mind was to change the algorithm so that it shows black when over lighter colors, and white when over darker colors.

I looked into the source and found where it's updating the color of the textbox field. There, I'm able to get the R, G, and B color values from 0 to 255.

In Javascript and jQuery, knowing the R, G, and B values of a background color, how can I switch the foreground color to either white or black so that it is readable?

Was it helpful?

Solution

Given the RGB/HSV conversion functions from Michael Jackson and this bit of HTML to play with:

<input type="text" id="pancakes">
<button id="margie">go</button>

Then something like this might be a decent starting point:

$('#margie').click(function() {
    var bg  = $('#pancakes').val();
    var rgb = bg.match(/../g);
    for(var i = 0; i < 3; ++i)
        rgb[i] = parseInt(rgb[i], 16);
    var hsv = rgbToHsv(rgb[0], rgb[1], rgb[2]);
    var fg  = 'ffffff';
    if(hsv[2] > 0.5)
        fg = '000000';
    $('#pancakes').css({
        color: '#' + fg,
        background: '#' + bg
    });
});

Demo: http://jsfiddle.net/ambiguous/xyA4a/

You might want to play with the hsv[2] > 0.5 and possibly look at the hue and saturation as well but just a simple value check should get you started. You might want to play with HSL rather than HSV and see which one works better for you.

OTHER TIPS

The conversion to hsl makes finding contrasting colors easy-

but it takes a bit to convert between rgb and hsl.

This works well enough for most cases- but it won't replace your eye.

function bW(r){
//r must be an rgb color array of 3 integers between 0 and 255. 

    var contrast= function(B, F){
        var abs= Math.abs,
        BG= (B[0]*299 + B[1]*587 + B[2]*114)/1000,
        FG= (F[0]*299 + F[1]*587 + F[2]*114)/1000,
        bright= Math.round(Math.abs(BG - FG)),
        diff= abs(B[0]-F[0])+abs(B[1]-F[1])+abs(B[2]-F[2]);
        return [bright, diff];
    }
    var c, w= [255, 255, 255], b= [0, 0, 0];
    if(r[1]> 200 && (r[0]+r[2])<50) c= b;
    else{
        var bc= contrast(b, r);
        var wc= contrast(w, r);
        if((bc[0]*4+bc[1])> (wc[0]*4+wc[1])) c= b;
        else if((wc[0]*4+wc[1])> (bc[0]*4+bc[1])) c= w;
        else c= (bc[0]< wc[0])? w:b;
    }
    return 'rgb('+c.join(',')+')';
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top