Reputation: 41
I have a Javascript canvas and I want to fill a rectangle on mouse hover with a "highlight" color. My rectangle has a dynamic color DC, so it can be anything from white to black and even a color with transparency. I need an algorithm to give me this "highlight" color starting from DC.
I think I have to test luminosity L over a threshold T:
if L < T increase luminosity of DC else decrease luminosity of DC
Is this a good approach or not?
I am not sure what to do for white and black. Should I just choose an appropriate color?
Upvotes: 3
Views: 736
Reputation: 41
My solution is as follows:
function colorLuminance(color, lum) {
var hex = colorToHex(color);
// validate hex string
hex = String(hex).replace(/[^0-9a-f]/gi, '');
if (hex.length < 6) {
hex = hex[0]+hex[0]+hex[1]+hex[1]+hex[2]+hex[2];
}
lum = lum || 0;
// convert to decimal and change luminosity
var rgb = "#", c, i;
for (i = 0; i < 3; i++) {
c = parseInt(hex.substr(i*2,2), 16);
c = Math.round(Math.min(Math.max(0, c + (c * lum)), 255)).toString(16);
rgb += ("00"+c).substr(c.length);
}
return rgb;
}
function colorToHex(c) {
var m = /rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)/.exec(c);
return m ? '#' + (1 << 24 | m[1] << 16 | m[2] << 8 | m[3]).toString(16).substr(1) : c;
}
//returns brightness value from 0 to 255
function get_brightness(hexCode) {
// strip off any leading #
hexCode = hexCode.replace('#', '');
var c_r = parseInt(hexCode.substr(0, 2),16);
var c_g = parseInt(hexCode.substr(2, 2),16);
var c_b = parseInt(hexCode.substr(4, 2),16);
return ((c_r * 299) + (c_g * 587) + (c_b * 114)) / 1000;
}
function highlightColor(color, lum) {
var hex = colorToHex(color);
if (get_brightness(hex) > 160) {
// too bright, need to darken it
if (lum > 0) {
lum = -lum;
}
} else {
if (lum < 0) {
lum = -lum;
}
}
return colorLuminance(color, lum);
}
Upvotes: 1
Reputation: 845
You can use something like this:
Check this example: http://jsfiddle.net/bocanegra_carlos/8ej4r02f/
// Get a contrasting Hex color value for a given color
// @param {String} hexColor: Hexadecimal color value (i.e. "#FF0000")
// @param {String} conversionType: Conversion type [YIQ|Opposite|50%]
// @return {String}
function getHighlightColor (hexColor, conversionType) {
if (!isValidColor(hexColor)) return "#000000";
switch (conversionType){
case "yiq":
// YIQ (Based on luminosity)
// *****************
hexColor = hexColor.substr(1);
if (hexColor.length == 3) {
var r = parseInt(hexColor.substr(0,1) + hexColor.substr(0,1),16);
var g = parseInt(hexColor.substr(1,1) + hexColor.substr(1,1),16);
var b = parseInt(hexColor.substr(2,1) + hexColor.substr(2,1),16);
}
else {
var r = parseInt(hexColor.substr(0,2),16);
var g = parseInt(hexColor.substr(2,2),16);
var b = parseInt(hexColor.substr(4,2),16);
}
var yiq = ((r*299)+(g*587)+(b*114))/1000;
return (yiq >= 128) ? '#000000' : '#FFFFFF';
break;
case "opposite":
// Opposite Color
// *****************
hexColor = hexColor.substring(1);
colorLength = hexColor.length;
hexColor = parseInt(hexColor, 16);
hexColor = 0xFFFFFF ^ hexColor;
hexColor = hexColor.toString(16);
if (colorLength == 6)
hexColor = ("000000" + hexColor).slice(-6);
else if (colorLength == 3)
hexColor = ("000" + hexColor).slice(-3);
else
hexColor = "000000";
return "#" + hexColor;
break;
case "50%":
// 50% (Black / White)
// *****************
hexColor = hexColor.substring(1)
if (hexColor.length == 4)
hexColor =
hexColor.substr(0,1) + hexColor.substr(0,1) +
hexColor.substr(1,1) + hexColor.substr(1,1) +
hexColor.substr(2,1) + hexColor.substr(2,1);
return (parseInt(hexColor, 16) > (0xffffff/2)) ? '#000000':'#FFFFFF';
}
}
// Validate the input value is a valid Hex color (i.e. Valid colors "#FF3400" or "#A9F". Invalid Colors "ASD102", "gray")
// @param {String} value: Value to test
// @return {Boolean}
function isValidColor(value){
var hexColorRegExp = new RegExp(/(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i);
return hexColorRegExp.test(value);
}
Upvotes: 2