Reputation: 229
how can i change this calculation to a darker and not brighter color?
function increase_brightness(hex, percent){
// strip the leading # if it's there
hex = hex.replace(/^\s*#|\s*$/g, '');
// convert 3 char codes --> 6, e.g. `E0F` --> `EE00FF`
if(hex.length == 3){
hex = hex.replace(/(.)/g, '$1$1');
}
var r = parseInt(hex.substr(0, 2), 16),
g = parseInt(hex.substr(2, 2), 16),
b = parseInt(hex.substr(4, 2), 16);
return '#' +
((0|(1<<8) + r + (256 - r) * percent / 100).toString(16)).substr(1) +
((0|(1<<8) + g + (256 - g) * percent / 100).toString(16)).substr(1) +
((0|(1<<8) + b + (256 - b) * percent / 100).toString(16)).substr(1);
}
src = JavaScript Calculate brighter colour
demo http://jsbin.com/utavax/3/edit
Upvotes: 4
Views: 5881
Reputation: 3748
I updated your original function to do a cheap version of lightening/darkening by basically multiplying a percentage (up or down) off the original RGB values.
function adjust(hexInput: string, percent: number) {
let hex = hexInput;
// strip the leading # if it's there
hex = hex.replace(/^\s*#|\s*$/g, "");
// convert 3 char codes --> 6, e.g. `E0F` --> `EE00FF`
if (hex.length === 3) {
hex = hex.replace(/(.)/g, "$1$1");
}
let r = parseInt(hex.substr(0, 2), 16);
let g = parseInt(hex.substr(2, 2), 16);
let b = parseInt(hex.substr(4, 2), 16);
const calculatedPercent = (100 + percent) / 100;
r = Math.round(Math.min(255, Math.max(0, r * calculatedPercent)));
g = Math.round(Math.min(255, Math.max(0, g * calculatedPercent)));
b = Math.round(Math.min(255, Math.max(0, b * calculatedPercent)));
return `#${r.toString(16).toUpperCase()}${g.toString(16).toUpperCase()}${b
.toString(16)
.toUpperCase()}`;
}
console.log(adjust("#49D174", -14)) // Darken by 14% = #3FB464
console.log(adjust("#49D174", -27)) // Darken by 27% = #359955
The function takes the percent as an integer, but could easily be modified for a decimal. Negative to darken, positive to lighten.
Upvotes: 4
Reputation: 12275
I've taken the main idea from Stylus (1, 2) and a few code parts from Stack Overflow answers and produced a library, darken_color.js.
Here are a few usage examples:
darken('lightgreen', '0.1'); // -> #63e763
darken('lightgreen', '10'); // -> #63e763
darken('#90EE90', '10'); // -> #63e763
darken('#9e9', '10%'); // -> #98ed98
Upvotes: 0
Reputation: 6751
You can change
return '#' +
((0|(1<<8) + r + (256 - r) * percent / 100).toString(16)).substr(1) +
((0|(1<<8) + g + (256 - g) * percent / 100).toString(16)).substr(1) +
((0|(1<<8) + b + (256 - b) * percent / 100).toString(16)).substr(1);
to
return '#' +
((0|(1<<8) + r * (1 - percent / 100)).toString(16)).substr(1) +
((0|(1<<8) + g * (1 - percent / 100)).toString(16)).substr(1) +
((0|(1<<8) + b * (1 - percent / 100).toString(16)).substr(1);
will fix your problem. demo.
But darker color is not a good definition. Darker can be interpreted as less brightness or less saturation. So the better approach is to convert the RGB color space to HSB color space, and tweak the S/B channels, then convert them back.
A little explanation on why negative value to original code is not OK.
Give -100 as percent, and some channel, say r, less than 128. Then
r + (256 - r) * percent / 100
is less than 0, after plus 1 << 8
= 256
((0|(1<<8) + r + (256 - r) * percent / 100)
is less than 256.
Take a number less than 256 will generate at most two hex digits by calling toString(16)
, so .substr(1)
will contain 0 or 1 digit only. By combining all these wrong digits together will not generate a proper color in hex representation.
Upvotes: 6
Reputation: 5664
return '#' +
((0|(1<<8) + r + (256 - r) * percent / 100).toString(16)).substr(1) +
((0|(1<<8) + g + (256 - g) * percent / 100).toString(16)).substr(1) +
((0|(1<<8) + b + (256 - b) * percent / 100).toString(16)).substr(1);
Here you are adding some percentage of r
, g
and b
to current values which makes the color lighter. If you use a negative value for percentage, it will decrease from current values and make the color darker.
Upvotes: -1