简体   繁体   English

JavaScript 计算更亮的颜色

[英]JavaScript Calculate brighter colour

I have a colour value in JS as a string我在 JS 中有一个颜色值作为字符串

#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, eg我将如何以编程方式计算这种颜色的更亮/更亮版本,例如#ff4848 ,并能够通过百分比计算亮度,例如

increase_brightness('#ff0000', 50); // would make it 50% brighter
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
 **/

Update更新

@zyklus's answer is simpler and has the same effect. @zyklus 的回答更简单,效果也一样。 Please refer to this answer only if you are interested in converting between RGB and HSL.仅当您对 RGB 和 HSL 之间的转换感兴趣时,请参阅此答案。


To set the brightness of RGB:要设置 RGB 的亮度:

  1. Convert RGB to HSL将 RGB 转换为 HSL

  2. Set the brightness of HSL设置HSL的亮度

  3. Convert back from HSL to RGB从 HSL 转换回 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此链接曾经包含将 RGB 转换为 HSL 并反转的代码: 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/检查此链接: http : //jsfiddle.net/sangdol/euSLy/4/

And this is the increase_brightness() function:这是increase_brightness()函数:

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.您可以将负值作为percent参数传递以使其变暗。

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:如果有人需要它,我将颜色亮度 JavaScript 代码转换为项目的 ASP / VBScript 并想与您分享:

'::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

That way you won't need any conversion of the source color.这样您就不需要对源颜色进行任何转换。
check out this fiddle : https://jsfiddle.net/4c47otou/看看这个小提琴: 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);

I found a variation of Sanghyun Lee's reply generates the best result.我发现 Sanghyun Lee 的回复的变体产生了最好的结果。

  1. Convert RGB to HSL将 RGB 转换为 HSL
  2. Set the brightness of HSL设置HSL的亮度
  3. Convert back from HSLto RGB从 HSL 转换回 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.由于亮度范围是 0 到 1,因此百分比可以应用于整个范围 (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.下图以 5% 的增量显示了更深和更浅的颜色。 Note, how the palette is reasonably smooth and often ends with black and white.请注意,调色板如何相当平滑,并且通常以黑色和白色结尾。

调色板

Palette with original approach - gets stuck at certain colors.具有原始方法的调色板 - 卡在某些颜色上。

在此处输入图片说明

I know this an old question, but I found no answer that simply manipulates css hsl color.我知道这是一个老问题,但我没有找到简单地操纵 css hsl 颜色的答案。 I found the old answers here to be too complex and slow, even producing poor results, so a different approach seems warranted.我发现这里的旧答案过于复杂和缓慢,甚至产生不良结果,因此似乎有必要采用不同的方法。 The following alternative is much more performant and less complex.以下替代方案的性能更高且更简单。

Of course, this answer requires you to use hsl colors throughout your app, otherwise you still have to do a bunch of conversions!当然,这个答案要求你在整个应用程序中使用hsl颜色,否则你仍然需要做一堆转换! Though, if you need to manipulate brightness eg in a game loop, you should be using hsl values anyway as they are much better suited for programmatic manipulation.但是,如果您需要在例如游戏循环中操作亮度,则无论如何您都应该使用 hsl 值,因为它们更适合于编程操作。 The only drawback with hsl from rgb as far as I can tell, is that it's harder to "read" what hue you're seeing like you can with rgb strings.据我所知,使用 rgb 中的 hsl 的唯一缺点是,很难像使用 rgb 字符串一样“读取”您所看到的色调。

function toHslArray(hslCss) {
    let sep = hslCss.indexOf(",") > -1 ? "," : " "
    return hslCss.substr(4).split(")")[0].split(sep)
}

function adjustHslBrightness(color, percent) {
    let hsl = toHslArray(color)
    return "hsl(" + hsl[0] + "," + hsl[1] + ", " + (percent + "%") + ")"
}

let hsl = "hsl(200, 40%, 40%)"
let hsl2 = adjustHslBrightness(hsl, 80)
// 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/实时示例: http : //jsfiddle.net/emM55/

Here is the increaseBrightness function with the RGB->HSL->RGB method.这里是 RGB->HSL->RGB 方法的增加亮度函数。 "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 HSL<->RGB 转换函数取自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 };
}

 function brighten(color, c) { const calc = (sub1,sub2)=> Math.min(255,Math.floor(parseInt(color.substr(sub1,sub2),16)*c)).toString(16).padStart(2,"0") return `#${calc(1,2)}${calc(3,2)}${calc(5,2)}` } const res = brighten("#23DA4C", .5) // "#116d26" console.log(res)

A variant with lodash : lodash一个变体:

// color('#EBEDF0', 30)
color(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('');
}

What I use:我使用的是:

//hex can be string or number
//rate: 1 keeps the color same. < 1 darken. > 1 lighten.
//to_string: set to true if you want the return value in string
function change_brightness(hex, rate, to_string = false) {
    if (typeof hex === 'string') {
        hex = hex.replace(/^\s*#|\s*$/g, '');
    } else {
        hex = hex.toString(16);
    }
    if (hex.length == 3) {
        hex = hex.replace(/(.)/g, '$1$1');
    } else {
        hex = ("000000" + hex).slice(-6);
    }
    let r = parseInt(hex.substr(0, 2), 16);
    let g = parseInt(hex.substr(2, 2), 16);
    let b = parseInt(hex.substr(4, 2), 16);

    let h, s, v;
    [h, s, v] = rgb2hsv(r, g, b);
    v = parseInt(v * rate);
    [r, g, b] = hsv2rgb(h, s, v);

    hex = ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
    if (to_string) return "#" + hex;
    return parseInt(hex, 16);
}

function rgb2hsv(r,g,b) {
    let v = Math.max(r,g,b), n = v-Math.min(r,g,b);
    let h = n && ((v === r) ? (g-b)/n : ((v === g) ? 2+(b-r)/n : 4+(r-g)/n)); 
    return [60*(h<0?h+6:h), v&&n/v, v];
}

function hsv2rgb(h,s,v) {
    let f = (n,k=(n+h/60)%6) => v - v*s*Math.max( Math.min(k,4-k,1), 0);
    return [f(5),f(3),f(1)];
}

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.然后应该很容易将您的颜色值分解为 RGB,进行调整,然后返回新的颜色代码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM