问题
I have a colour value in JS as a string
#ff0000
How would I go about programatically calculating a brighter/lighter version of this colour, for example #ff4848
, and be able to calculate the brightness via a percentage, e.g.
increase_brightness('#ff0000', 50); // would make it 50% brighter
回答1:
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);
}
/**
* ('#000000', 50) --> #808080
* ('#EEEEEE', 25) --> #F2F2F2
* ('EEE , 25) --> #F2F2F2
**/
回答2:
Update
@zyklus's answer is simpler and has the same effect. Please refer to this answer only if you are interested in converting between RGB and HSL.
To set the brightness of RGB:
Convert RGB to HSL
Set the brightness of HSL
Convert back from HSL to RGB
This link used to have code to convert RGB to HSL and reverse: http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript
/**
* Converts an RGB color value to HSL. Conversion formula
* adapted from http://en.wikipedia.org/wiki/HSL_color_space.
* Assumes r, g, and b are contained in the set [0, 255] and
* returns h, s, and l in the set [0, 1].
*
* @param Number r The red color value
* @param Number g The green color value
* @param Number b The blue color value
* @return Array The HSL representation
*/
function rgbToHsl(r, g, b){
r /= 255, g /= 255, b /= 255;
var max = Math.max(r, g, b), min = Math.min(r, g, b);
var h, s, l = (max + min) / 2;
if(max == min){
h = s = 0; // achromatic
}else{
var d = max - min;
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
switch(max){
case r: h = (g - b) / d + (g < b ? 6 : 0); break;
case g: h = (b - r) / d + 2; break;
case b: h = (r - g) / d + 4; break;
}
h /= 6;
}
return [h, s, l];
}
/**
* Converts an HSL color value to RGB. Conversion formula
* adapted from http://en.wikipedia.org/wiki/HSL_color_space.
* Assumes h, s, and l are contained in the set [0, 1] and
* returns r, g, and b in the set [0, 255].
*
* @param Number h The hue
* @param Number s The saturation
* @param Number l The lightness
* @return Array The RGB representation
*/
function hslToRgb(h, s, l){
var r, g, b;
if(s == 0){
r = g = b = l; // achromatic
}else{
function hue2rgb(p, q, t){
if(t < 0) t += 1;
if(t > 1) t -= 1;
if(t < 1/6) return p + (q - p) * 6 * t;
if(t < 1/2) return q;
if(t < 2/3) return p + (q - p) * (2/3 - t) * 6;
return p;
}
var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
var p = 2 * l - q;
r = hue2rgb(p, q, h + 1/3);
g = hue2rgb(p, q, h);
b = hue2rgb(p, q, h - 1/3);
}
return [r * 255, g * 255, b * 255];
}
I made some example with it. Check this link: http://jsfiddle.net/sangdol/euSLy/4/
And this is the increase_brightness()
function:
function increase_brightness(rgbcode, percent) {
var r = parseInt(rgbcode.slice(1, 3), 16),
g = parseInt(rgbcode.slice(3, 5), 16),
b = parseInt(rgbcode.slice(5, 7), 16),
HSL = rgbToHsl(r, g, b),
newBrightness = HSL[2] + HSL[2] * (percent / 100),
RGB;
RGB = hslToRgb(HSL[0], HSL[1], newBrightness);
rgbcode = '#'
+ convertToTwoDigitHexCodeFromDecimal(RGB[0])
+ convertToTwoDigitHexCodeFromDecimal(RGB[1])
+ convertToTwoDigitHexCodeFromDecimal(RGB[2]);
return rgbcode;
}
function convertToTwoDigitHexCodeFromDecimal(decimal){
var code = Math.round(decimal).toString(16);
(code.length > 1) || (code = '0' + code);
return code;
}
You can pass a negative value as a percent
argument to make it darken.
回答3:
In case anyone needs it, I converted the color brightness JavaScript code to ASP / VBScript for a project and thought I would share it with you:
'::Color Brightness (0-100)
'ex. ColorBrightness("#FF0000",25) 'Darker
'ex. ColorBrightness("#FF0000",50) 'Mid
'ex. ColorBrightness("#FF0000",75) 'Lighter
Function ColorBrightness(strRGB,intBrite)
strRGB = Replace(strRGB,"#","")
r = CInt("&h" & Mid(strRGB,1,2))
g = CInt("&h" & Mid(strRGB,3,2))
b = CInt("&h" & Mid(strRGB,5,2))
arrHSL = RGBtoHSL(r, g, b)
dblOrigBrite = CDbl(arrHSL(2) * 100)
arrRGB = HSLtoRGB(arrHSL(0), arrHSL(1), intBrite/100)
newRGB = "#" & HEXtoDEC(arrRGB(0)) & HEXtoDEC(arrRGB(1)) & HEXtoDEC(arrRGB(2))
ColorBrightness = newRGB
End Function
'::RGB to HSL Function
Function RGBtoHSL(r,g,b)
r = CDbl(r/255)
g = CDbl(g/255)
b = CDbl(b/255)
max = CDbl(MaxCalc(r & "," & g & "," & b))
min = CDbl(MinCalc(r & "," & g & "," & b))
h = CDbl((max + min) / 2)
s = CDbl((max + min) / 2)
l = CDbl((max + min) / 2)
If max = min Then
h = 0
s = 0
Else
d = max - min
s = IIf(l > 0.5, d / (2 - max - min), d / (max + min))
Select Case CStr(max)
Case CStr(r)
h = (g - b) / d + (IIf(g < b, 6, 0))
Case CStr(g)
h = (b - r) / d + 2
Case CStr(b)
h = (r - g) / d + 4
End Select
h = h / 6
End If
RGBtoHSL = Split(h & "," & s & "," & l, ",")
End Function
'::HSL to RGB Function
Function HSLtoRGB(h,s,l)
If s = 0 Then
r = l
g = l
b = l
Else
q = IIf(l < 0.5, l * (1 + s), l + s - l * s)
p = 2 * l - q
r = HUEtoRGB(p, q, h + 1/3)
g = HUEtoRGB(p, q, h)
b = HUEtoRGB(p, q, h - 1/3)
End If
HSLtoRGB = Split(r * 255 & "," & g * 255 & "," & b * 255, ",")
End Function
'::Hue to RGB Function
Function HUEtoRGB(p,q,t)
If CDbl(t) < 0 Then t = t + 1
If CDbl(t) > 1 Then t = t - 1
If CDbl(t) < (1/6) Then
HUEtoRGB = p + (q - p) * 6 * t
Exit Function
End If
If CDbl(t) < (1/2) Then
HUEtoRGB = q
Exit Function
End If
If CDbl(t) < (2/3) Then
HUEtoRGB = p + (q - p) * (2/3 - t) * 6
Exit Function
End If
HUEtoRGB = p
End Function
'::Hex to Decimal Function
Function HEXtoDEC(d)
h = Hex(Round(d,0))
h = Right(String(2,"0") & h,2)
HEXtoDEC = h
End Function
'::Max Function
Function MaxCalc(valList)
valList = Split(valList,",")
b = 0
For v = 0 To UBound(valList)
a = valList(v)
If CDbl(a) > CDbl(b) Then b = a
Next
MaxCalc = b
End Function
'::Min Function
Function MinCalc(valList)
valList = Split(valList,",")
For v = 0 To UBound(valList)
a = valList(v)
If b = "" Then b = a
If CDbl(a) < CDbl(b) AND b <> "" Then b = a
Next
MinCalc = b
End Function
'::IIf Emulation Function
Function IIf(condition,conTrue,conFalse)
If (condition) Then
IIf = conTrue
Else
IIf = conFalse
End If
End Function
回答4:
// color is a hex color like #aaaaaa and percent is a float, 1.00=100%
// increasing a color by 50% means a percent value of 1.5
function brighten(color, percent) {
var r=parseInt(color.substr(1,2),16);
var g=parseInt(color.substr(3,2),16);
var b=parseInt(color.substr(5,2),16);
return '#'+
Math.min(255,Math.floor(r*percent)).toString(16)+
Math.min(255,Math.floor(g*percent)).toString(16)+
Math.min(255,Math.floor(b*percent)).toString(16);
}
Live sample: http://jsfiddle.net/emM55/
回答5:
Here is the increaseBrightness function with the RGB->HSL->RGB method. "amount" should be in percent.
HSL<->RGB conversion functions taken from http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript
function increaseBrightness( color, amount ) {
var r = parseInt(color.substr(1, 2), 16);
var g = parseInt(color.substr(3, 2), 16);
var b = parseInt(color.substr(5, 2), 16);
hsl = rgbToHsl( r, g, b );
hsl.l += hsl.l + (amount / 100);
if( hsl.l > 1 ) hsl.l = 1;
rgb = hslToRgb( hsl.h, hsl.s, hsl.l );
var v = rgb.b | (rgb.g << 8) | (rgb.r << 16);
return '#' + v.toString(16);
}
function rgbToHsl(r, g, b){
r /= 255, g /= 255, b /= 255;
var max = Math.max(r, g, b), min = Math.min(r, g, b);
var h, s, l = (max + min) / 2;
if(max == min){
h = s = 0; // achromatic
}else{
var d = max - min;
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
switch(max){
case r: h = (g - b) / d + (g < b ? 6 : 0); break;
case g: h = (b - r) / d + 2; break;
case b: h = (r - g) / d + 4; break;
}
h /= 6;
}
return {'h':h, 's':s, 'l':l};
}
function hslToRgb(h, s, l){
var r, g, b;
if(s == 0){
r = g = b = l; // achromatic
}else{
function hue2rgb(p, q, t){
if(t < 0) t += 1;
if(t > 1) t -= 1;
if(t < 1/6) return p + (q - p) * 6 * t;
if(t < 1/2) return q;
if(t < 2/3) return p + (q - p) * (2/3 - t) * 6;
return p;
}
var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
var p = 2 * l - q;
r = hue2rgb(p, q, h + 1/3);
g = hue2rgb(p, q, h);
b = hue2rgb(p, q, h - 1/3);
}
return { 'r':r * 255, 'g':g * 255, 'b':b * 255 };
}
回答6:
That way you won't need any conversion of the source color.
check out this fiddle : https://jsfiddle.net/4c47otou/
increase_brightness = function(color,percent){
var ctx = document.createElement('canvas').getContext('2d');
ctx.fillStyle = color;
ctx.fillRect(0,0,1,1);
var color = ctx.getImageData(0,0,1,1);
var r = color.data[0] + Math.floor( percent / 100 * 255 );
var g = color.data[1] + Math.floor( percent / 100 * 255 );
var b = color.data[2] + Math.floor( percent / 100 * 255 );
return 'rgb('+r+','+g+','+b+')';
}
Example usage :
increase_brightness('#0000ff',20);
increase_brightness('khaki',20);
increase_brightness('rgb(12, 7, 54)',20);
回答7:
I found a variation of Sanghyun Lee's reply generates the best result.
- Convert RGB to HSL
- Set the brightness of HSL
- Convert back from HSLto RGB
The difference/variation is how you increase/decrease the brightness.
newBrightness = HSL[2] + HSL[2] * (percent / 100) // Original code
Instead of applying a percentage on the current brightness, it works better if it is treated as absolute increment/decrement. Since the luminosity range is 0 to 1, the percent can be applied on the whole range (1 - 0) * percent/100.
newBrightness = HSL[2] + (percent / 100);
newBrightness = Math.max(0, Math.min(1, newBrightness));
Another nice property of this approach is increment & decrement negate each other.
Image below shows darker and lighter colors with 5% increment. Note, how the palette is reasonably smooth and often ends with black and white.
Palette with original approach - gets stuck at certain colors.
回答8:
First get a quick understanding of hex color codes.
Then it should be pretty easy to break down your color value into RGB, make the adjustments and then return the new color code.
回答9:
Simplified version of the accepted solution with lodash
:
// colorIncreaseBrightness('#EBEDF0', 30)
colorIncreaseBrightness(hex, percent) {
return '#' + _(hex.replace('#', '')).chunk(2)
.map(v => parseInt(v.join(''), 16))
.map(v => ((0 | (1 << 8) + v + (256 - v) * percent / 100).toString(16))
.substr(1)).join('');
}
来源:https://stackoverflow.com/questions/6443990/javascript-calculate-brighter-colour