首页 文章

以编程方式使六角颜色(或rgb和混合颜色)变亮或变暗

提问于
浏览
412

这是我正在努力以编程方式使特定量的十六进制颜色变亮或变暗的功能 . 只需输入一个像 "3F6D2A" 这样的字符串作为颜色( col )和一个base10整数( amt )来获得变亮或变暗的量 . 为了变暗,传入负数(即-20) .

我这样做的原因是因为我找到的所有解决方案,到目前为止,它们似乎使问题过于复杂 . 我感觉只需几行代码即可完成 . 如果您发现任何问题,请告知我们,或者进行任何调整以使其加速 .

function LightenDarkenColor(col,amt) {
    col = parseInt(col,16);
    return (((col & 0x0000FF) + amt) | ((((col>> 8) & 0x00FF) + amt) << 8) | (((col >> 16) + amt) << 16)).toString(16);
}

对于开发使用,这里是一个更容易阅读的版本:

function LightenDarkenColor(col,amt) {
    var num = parseInt(col,16);
    var r = (num >> 16) + amt;
    var b = ((num >> 8) & 0x00FF) + amt;
    var g = (num & 0x0000FF) + amt;
    var newColor = g | (b << 8) | (r << 16);
    return newColor.toString(16);
}

最后一个版本处理颜色,可能(或可能不)在开头有“#” . 另外调整不正确的颜色值:

function LightenDarkenColor(col,amt) {
    var usePound = false;
    if ( col[0] == "#" ) {
        col = col.slice(1);
        usePound = true;
    }

    var num = parseInt(col,16);

    var r = (num >> 16) + amt;

    if ( r > 255 ) r = 255;
    else if  (r < 0) r = 0;

    var b = ((num >> 8) & 0x00FF) + amt;

    if ( b > 255 ) b = 255;
    else if  (b < 0) b = 0;

    var g = (num & 0x0000FF) + amt;

    if ( g > 255 ) g = 255;
    else if  ( g < 0 ) g = 0;

    return (usePound?"#":"") + (g | (b << 8) | (r << 16)).toString(16);
}

好吧,所以现在它不仅仅是几行,但它似乎更简单,如果你不使用“#”并且不需要检查超出范围的颜色,它只是几行 .

如果不使用“#”,您只需将其添加到以下代码中:

var myColor = "3F6D2A";
myColor = LightenDarkenColor(myColor,10);
thePlaceTheColorIsUsed = ("#" + myColor);

我想我的主要问题是,我在这里是否正确?这不包括某些(正常)情况吗?

11 回答

  • 3

    TL;DR? - 想要简单的变亮/变暗(阴影)?省略到版本2,选择一个RGB或Hex . - 想要一个功能齐全的着色器/搅拌器/转换器,带有错误检查和alpha和3位十六进制?在底部附近使用版本3 .

    使用3.1版:jsfiddle > shadeBlendConvert Example

    GitHub版本3.1:Goto GitHub > PJs > pSBC


    经过一番思考......我决定回答我自己的问题 . 一年半之后 . 这真是一个冒险,有来自几个有用的用户的想法,我感谢你们!这个是给团队的!虽然它不一定是我想要的答案 . 因为如果James Khoury说的是真的,那么在javascript中没有真正的十六进制数学,我必须使用小数,这种双重转换是必要的 . 如果我们做出这个假设,那么这可能是我见过(或者可以想到)以百分比变亮(增加白色)或变暗(加黑)任意RBG颜色的最快方式 . 它也解释了Cool Acid在回答这个问题时提到的问题(填0页) . 但是这个版本只调用 toString 一次 . 这也导致超出范围(它将强制0和255作为限制) .

    但要注意,颜色输入必须是7个字符,如 #08a35c . (如果使用顶级版本,则为6)

    感谢Pablo的灵感和使用百分比的想法 . 为此,我将保持功能名称相同!大声笑!但是,这个是不同的,因为它将百分比标准化为255,从而为每种颜色添加相同的量(更多白色) . 如果你传递100为 percent 它将使你的颜色纯白色 . 如果为 percent 传入0,则不会发生任何事情 . 如果为 percent 传入1,它将为所有颜色添加3个阴影(每1%2.55个阴影,圆角) . 所以你真的通过一定比例的白色(或黑色,使用负面) . 因此,此版本允许您减轻纯红色(FF0000),例如 .

    我还使用了Keith Mashinter对这个问题的回答:How to convert decimal to hex in JavaScript?

    我删除了一些似乎不必要的括号 . (比如在双三元语句和制作G中)不确定这是否会在某些环境中混淆运算符优先级 . 在FireFox中测试得很好 .

    function shadeColor1(color, percent) {  // deprecated. See below.
        var num = parseInt(color,16),
        amt = Math.round(2.55 * percent),
        R = (num >> 16) + amt,
        G = (num >> 8 & 0x00FF) + amt,
        B = (num & 0x0000FF) + amt;
        return (0x1000000 + (R<255?R<1?0:R:255)*0x10000 + (G<255?G<1?0:G:255)*0x100 + (B<255?B<1?0:B:255)).toString(16).slice(1);
    }
    

    或者,如果您希望它处理“#”:

    function shadeColor1(color, percent) {  // deprecated. See below.
        var num = parseInt(color.slice(1),16), amt = Math.round(2.55 * percent), R = (num >> 16) + amt, G = (num >> 8 & 0x00FF) + amt, B = (num & 0x0000FF) + amt;
        return "#" + (0x1000000 + (R<255?R<1?0:R:255)*0x10000 + (G<255?G<1?0:G:255)*0x100 + (B<255?B<1?0:B:255)).toString(16).slice(1);
    }
    

    这两行代码怎么样?

    编辑:修复B < - > G交换蠢 . 谢谢svachalek!


    -- UPDATE - Version 2 with Blending --

    一年多一点之后,又一次,它还在继续 . 但这次我认为它完成了 . 注意到提到的关于不使用HSL来正确减轻颜色的问题 . 有一种技术可以消除大部分不准确性而无需转换为HSL . 主要问题是颜色通道在其余颜色之前会完全饱和 . 在那之后导致色调的变化 . 我发现这些问题hereherehere让我走上正轨 . Mark Ransom's post向我展示了不同之处,Keith's post向我展示了道路 . Lerp是救世主 . 它与混合颜色相同,所以我也创建了一个 blendColors 函数 .


    TL;DR - 对于简单的变亮/变暗使用此功能 shadeColor2 如下 . 或者下面的RGB对应 shadeRGBColor ,给我一票 . 但是,如果你想要 any and/or all 的好东西 . 例如能够同时使用RGB和Hex颜色,错误检查,3位十六进制解码,混合,Alpha通道和RGB2Hex / Hex2RGB转换 . 然后,跳到版本3以获取 shadeBlendConvert 以获得所有的花里胡哨,并给我两张选票 . 如果需要,您可以删除几行以删除其中一些功能 . 如果您记得上面的版本1 shadeColor1deprecated 用于所有用途,您将获得投票 .


    所以,不用多说:

    -Version 2 Hex-

    function shadeColor2(color, percent) {   
        var f=parseInt(color.slice(1),16),t=percent<0?0:255,p=percent<0?percent*-1:percent,R=f>>16,G=f>>8&0x00FF,B=f&0x0000FF;
        return "#"+(0x1000000+(Math.round((t-R)*p)+R)*0x10000+(Math.round((t-G)*p)+G)*0x100+(Math.round((t-B)*p)+B)).toString(16).slice(1);
    }
    
    function blendColors(c0, c1, p) {
        var f=parseInt(c0.slice(1),16),t=parseInt(c1.slice(1),16),R1=f>>16,G1=f>>8&0x00FF,B1=f&0x0000FF,R2=t>>16,G2=t>>8&0x00FF,B2=t&0x0000FF;
        return "#"+(0x1000000+(Math.round((R2-R1)*p)+R1)*0x10000+(Math.round((G2-G1)*p)+G1)*0x100+(Math.round((B2-B1)*p)+B1)).toString(16).slice(1);
    }
    

    更进一步:

    没有错误检查,因此传递的超出范围的值将导致意外结果 . 同样,颜色输入必须是7个字符,如 #08a35c . 但所有其他好东西仍然在这里像输出范围封顶(00-FF输出),填充(0A),处理 # ,并可用于纯色,如 #FF0000 .

    这个新版本的shadeColor为其第二个参数提供了一个浮点数 . 对于 shadeColor2 ,第二个(百分比)参数的有效范围是 -1.01.0 .

    对于 blendColors ,第三个(百分比)参数的有效范围是 0.01.0 ,此处不允许使用负数 .

    这个新版本不再采用纯白色的百分比,就像旧版本一样 . 它占据了DISTANCE的一定百分比,从纯白色的颜色 . 在旧版本中,很容易使颜色饱和,因此,当使用相当大的百分比时,许多颜色会计算为纯白色 . 这种新方法,如果你传入 1.0 或纯黑,它只计算为纯白色,使用 -1.0 .

    调用 blendColors(color, "#FFFFFF", 0.5)shadeColor2(color,0.5) 相同 . 除此之外, blendColors(color,"#000000", 0.5)shadeColor2(color,-0.5) 相同 . 只是一触即慢 .

    shadeColor2shadeColor1 慢,但不是显着的数量 . (等等,这是一个自相矛盾的陈述!)

    获得的准确度可以在这里看到:

    -- Version 2 RGB --

    function shadeRGBColor(color, percent) {
        var f=color.split(","),t=percent<0?0:255,p=percent<0?percent*-1:percent,R=parseInt(f[0].slice(4)),G=parseInt(f[1]),B=parseInt(f[2]);
        return "rgb("+(Math.round((t-R)*p)+R)+","+(Math.round((t-G)*p)+G)+","+(Math.round((t-B)*p)+B)+")";
    }
    
    function blendRGBColors(c0, c1, p) {
        var f=c0.split(","),t=c1.split(","),R=parseInt(f[0].slice(4)),G=parseInt(f[1]),B=parseInt(f[2]);
        return "rgb("+(Math.round((parseInt(t[0].slice(4))-R)*p)+R)+","+(Math.round((parseInt(t[1])-G)*p)+G)+","+(Math.round((parseInt(t[2])-B)*p)+B)+")";
    }
    

    用途:

    var color1 = "rbg(63,131,163)";
    var lighterColor = shadeRGBColor(color1, 0.5);  //  rgb(159,193,209)
    var darkerColor = shadeRGBColor(color1, -0.25); //  rgb(47,98,122)
    
    var color2 = "rbg(244,128,0)";
    var blend1 = blendRGBColors(color1, color2, 0.75);  //  rgb(199,129,41)
    var blend2 = blendRGBColors(color2, color1, 0.62);  //  rgb(132,130,101)
    

    -- Version 2 Universal A --

    function shade(color, percent){
        if (color.length > 7 ) return shadeRGBColor(color,percent);
        else return shadeColor2(color,percent);
    }
    
    function blend(color1, color2, percent){
        if (color1.length > 7) return blendRGBColors(color1,color2,percent);
        else return blendColors(color1,color2,percent);
    }
    

    用法:

    var color1 = shade("rbg(63,131,163)", 0.5);
    var color2 = shade("#3f83a3", 0.5);
    var color3 = blend("rbg(63,131,163)", "rbg(244,128,0)", 0.5);
    var color4 = blend("#3f83a3", "#f48000", 0.5);
    

    -- Version 2 Universal B --

    好的!这个答案的流行让我觉得我可以做一个更好的通用版本 . 所以你走了!此版本是RGB和Hex颜色的一体化功能复制/粘贴着色器/混合器 . 这个与上面提供的其他Uni版本没什么不同 . 除了它更小,只有一个功能粘贴和使用 . 如果你将它压缩成一行,我认为大小从大约1,592个字符变为557个字符 . 当然,如果你不需要像这样的通用版本,无论如何,哈哈 . 只需使用上面更小,更快的版本之一;适合您的配色方案 . 继续......在某些方面它会更快一些,在某些方面它会慢一点 . 我没有做任何最终的速度测试分析 . 有两个使用差异:首先,百分比现在是函数的第一个参数,而不是最后一个 . 其次,混合时,可以使用负数 . 他们只会转换为正数 .

    不再多了:

    function shadeBlend(p,c0,c1) {
        var n=p<0?p*-1:p,u=Math.round,w=parseInt;
        if(c0.length>7){
            var f=c0.split(","),t=(c1?c1:p<0?"rgb(0,0,0)":"rgb(255,255,255)").split(","),R=w(f[0].slice(4)),G=w(f[1]),B=w(f[2]);
            return "rgb("+(u((w(t[0].slice(4))-R)*n)+R)+","+(u((w(t[1])-G)*n)+G)+","+(u((w(t[2])-B)*n)+B)+")"
        }else{
            var f=w(c0.slice(1),16),t=w((c1?c1:p<0?"#000000":"#FFFFFF").slice(1),16),R1=f>>16,G1=f>>8&0x00FF,B1=f&0x0000FF;
            return "#"+(0x1000000+(u(((t>>16)-R1)*n)+R1)*0x10000+(u(((t>>8&0x00FF)-G1)*n)+G1)*0x100+(u(((t&0x0000FF)-B1)*n)+B1)).toString(16).slice(1)
        }
    }
    

    用法:

    var color1 = "#FF343B";
    var color2 = "#343BFF";
    var color3 = "rgb(234,47,120)";
    var color4 = "rgb(120,99,248)";
    var shadedcolor1 = shadeBlend(0.75,color1);
    var shadedcolor3 = shadeBlend(-0.5,color3);
    var blendedcolor1 = shadeBlend(0.333,color1,color2);
    var blendedcolor34 = shadeBlend(-0.8,color3,color4); // Same as using 0.8
    

    Now 它可能是完美的! ;) @ Mevin

    *** V2 OTHER LANGUAGES ***

    -- Swift Extension - RGB (by Matej Ukmar) --

    extension UIColor {
        func shadeColor(factor: CGFloat) -> UIColor {
            var r: CGFloat = 0
            var g: CGFloat = 0
            var b: CGFloat = 0
            var a: CGFloat = 0
            var t: CGFloat = factor < 0 ? 0 : 1
            var p: CGFloat = factor < 0 ? -factor : factor
            getRed(&r, green: &g, blue: &b, alpha: &a)
            r = (t-r)*p+r
            g = (t-g)*p+g
            b = (t-b)*p+b
            return UIColor(red: r, green: g, blue: b, alpha: a)
        }
    }
    

    -- PHP Version - HEX (by Kevin M) --

    function shadeColor2($color, $percent) {
        $color = str_replace("#", "", $color);
        $t=$percent<0?0:255;
        $p=$percent<0?$percent*-1:$percent;
        $RGB = str_split($color, 2);
        $R=hexdec($RGB[0]);
        $G=hexdec($RGB[1]);
        $B=hexdec($RGB[2]);
        return '#'.substr(dechex(0x1000000+(round(($t-$R)*$p)+$R)*0x10000+(round(($t-$G)*$p)+$G‌​)*0x100+(round(($t-$B)*$p)+$B)),1);
    }
    

    -- UPDATE -- Version 3.1 Universal --

    (这已添加到我的图书馆GitHub

    在几个月内,它将是自上一个通用版本以来的又一年 . 所以...感谢sricks's富有洞察力的评论 . 我已经决定再次将它提升到一个新的水平 . 它不再像它开始的两线速度恶魔,哈哈 . 但是,就它的作用而言,它非常快而且很小 . 它大约1600字节 . 如果您删除ErrorChecking并删除3位数字解码,您可以将其降低到大约1200字节并且速度更快 . 这是关于K的很多力量 . 想象一下,你可以将它加载到Commodore64上,并且仍然可以容纳50多个它们! (忽略JavaScript引擎大于63k的事实)

    显然还有更多的事情要做:

    const shadeBlendConvert = function (p, from, to) {
        if(typeof(p)!="number"||p<-1||p>1||typeof(from)!="string"||(from[0]!='r'&&from[0]!='#')||(to&&typeof(to)!="string"))return null; //ErrorCheck
        if(!this.sbcRip)this.sbcRip=(d)=>{
            let l=d.length,RGB={};
            if(l>9){
                d=d.split(",");
                if(d.length<3||d.length>4)return null;//ErrorCheck
                RGB[0]=i(d[0].split("(")[1]),RGB[1]=i(d[1]),RGB[2]=i(d[2]),RGB[3]=d[3]?parseFloat(d[3]):-1;
            }else{
                if(l==8||l==6||l<4)return null; //ErrorCheck
                if(l<6)d="#"+d[1]+d[1]+d[2]+d[2]+d[3]+d[3]+(l>4?d[4]+""+d[4]:""); //3 or 4 digit
                d=i(d.slice(1),16),RGB[0]=d>>16&255,RGB[1]=d>>8&255,RGB[2]=d&255,RGB[3]=-1;
                if(l==9||l==5)RGB[3]=r((RGB[2]/255)*10000)/10000,RGB[2]=RGB[1],RGB[1]=RGB[0],RGB[0]=d>>24&255;
            }
        return RGB;}
        var i=parseInt,r=Math.round,h=from.length>9,h=typeof(to)=="string"?to.length>9?true:to=="c"?!h:false:h,b=p<0,p=b?p*-1:p,to=to&&to!="c"?to:b?"#000000":"#FFFFFF",f=this.sbcRip(from),t=this.sbcRip(to);
        if(!f||!t)return null; //ErrorCheck
        if(h)return "rgb"+(f[3]>-1||t[3]>-1?"a(":"(")+r((t[0]-f[0])*p+f[0])+","+r((t[1]-f[1])*p+f[1])+","+r((t[2]-f[2])*p+f[2])+(f[3]<0&&t[3]<0?")":","+(f[3]>-1&&t[3]>-1?r(((t[3]-f[3])*p+f[3])*10000)/10000:t[3]<0?f[3]:t[3])+")");
        else return "#"+(0x100000000+r((t[0]-f[0])*p+f[0])*0x1000000+r((t[1]-f[1])*p+f[1])*0x10000+r((t[2]-f[2])*p+f[2])*0x100+(f[3]>-1&&t[3]>-1?r(((t[3]-f[3])*p+f[3])*255):t[3]>-1?r(t[3]*255):f[3]>-1?r(f[3]*255):255)).toString(16).slice(1,f[3]>-1||t[3]>-1?undefined:-2);
    }
    

    使用3.1版:jsfiddle > shadeBlendConvert Example

    此版本的核心数学与以前相同 . 但是,我做了一些重大的重构 . 这使得功能和控制更加强大 . 它现在固有地转换RGB2Hex和Hex2RGB .

    上面v2的所有旧功能都应该在这里 . 我试过测试一下,如果你发现任何错误,请发表评论 . 无论如何,这里有新功能:

    • 接受3位(或4位)HEX颜色代码,格式为#RGB(或#ARGB) . 它会扩展它们 . 删除标有 //3 digit 的行以删除此功能 .

    • 接受并混合Alpha通道 . 如果 from 颜色或 to 颜色具有Alpha通道,则结果将具有Alpha通道 . 如果两种颜色都具有Alpha通道,则结果将是使用给定百分比的两个Alpha通道的混合(就像它是正常颜色通道一样) . 如果两种颜色中只有一种具有alpha通道,则此alpha将直接传递给结果 . 这允许人们在保持透明水平的同时混合/遮蔽透明色 . 或者,如果透明级别也应该混合,请确保两种颜色都有alpha . 着色将通过alpha通道,如果你想要也混合alpha通道的基本着色,那么使用 rgb(0,0,0,1)rgb(255,255,255,1) 作为你的 to 颜色(或它们的十六进制等值) . 对于RGB颜色,生成的Alpha通道将四舍五入到小数点后4位 .
      现在使用混合时会隐式

    • RGB2Hex和Hex2RGB转换 . 结果颜色将始终采用 to 颜色的形式(如果存在) . 如果没有 to 颜色,则将 'c' 作为 to 颜色传递,它将变暗并转换 . 如果只需要转换,然后传递 0 作为百分比 .

    • 辅助功能也被添加到全局 . sbcRip 可以传递十六进制或rbg颜色,并返回包含此颜色信息的对象 . 它的形式为: {0:R,1:G,2:B,3:A} . R GB 的范围 0255 . 当没有alpha时: A-1 . 否则: A 的范围是 0.00001.0000 .

    • 已添加次要错误检查 . 这不完美 . 它仍然可以崩溃 . 但它会 grab 一些东西 . 基本上,如果结构在某些方面是错误的,或者如果百分比不是数字或超出范围,它将返回 null . 例如: shadeBlendConvert(0.5,"salt") = null ,因为它认为 #salt 是有效颜色 . 删除标有 //ErrorCheck 的四行以删除此功能 .

    用途:

    let color1 = "rgb(20,60,200)";
    let color2 = "rgba(20,60,200,0.67423)";
    let color3 = "#67DAF0";
    let color4 = "#5567DAF0";
    let color5 = "#F3A";
    let color6 = "#F3A9";
    let color7 = "rgb(200,60,20)";
    let color8 = "rgba(200,60,20,0.98631)";
    let c;
    
    // Shade (Lighten or Darken)
    c = shadeBlendConvert ( 0.42, color1 ); // rgb(20,60,200) + [42% Lighter] => rgb(119,142,223)
    c = shadeBlendConvert ( -0.4, color5 ); // #F3A + [40% Darker] => #991f66
    c = shadeBlendConvert ( 0.42, color8 ); // rgba(200,60,20,0.98631) + [42% Lighter] => rgba(223,142,119,0.98631)
    // Shade with Conversion (use "c" as your "to" color)
    c = shadeBlendConvert ( 0.42, color2, "c" ); // rgba(20,60,200,0.67423) + [42% Lighter] + [Convert] => #778edfac
    // RGB2Hex & Hex2RGB Conversion Only (set percentage to zero)
    c = shadeBlendConvert ( 0, color6, "c" ); // #F3A9 + [Convert] => rgba(255,51,170,0.6)
    // Blending
    c = shadeBlendConvert ( -0.5, color2, color8 ); // rgba(20,60,200,0.67423) + rgba(200,60,20,0.98631) + [50% Blend] => rgba(110,60,110,0.8303)
    c = shadeBlendConvert ( 0.7, color2, color7 ); // rgba(20,60,200,0.67423) + rgb(200,60,20) + [70% Blend] => rgba(146,60,74,0.67423)
    c = shadeBlendConvert ( 0.25, color3, color7 ); // #67DAF0 + rgb(200,60,20) + [25% Blend] => rgb(127,179,185)
    c = shadeBlendConvert ( 0.75, color7, color3 ); // rgb(200,60,20) + #67DAF0 + [75% Blend] => #7fb3b9
    // Error Checking
    c = shadeBlendConvert ( 0.42, "#FFBAA" ); // #FFBAA + [42% Lighter] => null  (Invalid Input Color)
    c = shadeBlendConvert ( 42, color1, color5 ); // rgb(20,60,200) + #F3A + [4200% Blend] => null  (Invalid Percentage Range)
    c = shadeBlendConvert ( 0.42, {} ); // [object Object] + [42% Lighter] => null  (Strings Only for Color)
    c = shadeBlendConvert ( "42", color1 ); // rgb(20,60,200) + ["42"] => null  (Numbers Only for Percentage)
    c = shadeBlendConvert ( 0.42, "salt" ); // salt + [42% Lighter] => null  (A Little Salt is No Good...)
    // Error Check Fails (Some Errors are not Caught)
    c = shadeBlendConvert ( 0.42, "#salt" ); // #salt + [42% Lighter] => #6b6b6b00  (...and a Pound of Salt is Jibberish)
    // Ripping
    c = sbcRip ( color4 ); // #5567DAF0 + [Rip] => [object Object] => {'0':85,'1':103,'2':218,'3':0.9412}
    

    我现在犹豫再次称这个......

    PT

    --EDIT:切换版本3以使用 let 和箭头功能,并将 this 添加到 sbcRip 调用 .

    ----===<| MAJOR EDIT(3/9/18) |>===----

    我很惭愧! (并且没有人提到这一点感到惊讶)显然我不会在我自己的项目中使用alpha通道......而且......显然我做了可怕的测试 . 版本3没有正确读取或写入alpha通道的颜色 . 有几点我要么错了,要么从未实际学过:

    • 带alpha的十六进制颜色是#RGBA(不是#ARGB) . 版本3正在向后读取和写入 .
      带有alphas的

    • RGB颜色必须是 rgba() 而不是 rgb() ;版本3从不输出 rgba() .

    • 版本3不接受 rgba() 但确实接受 rgb() 中的alphas,这不应该发生 .

    我刚刚用3.1版替换了版本3,解决了这些问题 . 我没有把它作为一个单独的函数发布在这里;看到旧版本3应该从存在中移除并替换为此版本 . 这就是我所做的 . 上面的版本3实际上是版本3.1 .

    上面的所有旧功能仍然在这些更新:

    • 使用Alpha通道正确读取和写入颜色 . Hex和RGB都有 .

    • to 颜色现在接受字符串颜色或假(仍然可以是 undefined ) .

    • 该函数现在是常量 .

    ......我很高兴我犹豫再说一遍 . 我们在这里,又过了一年左右......还在完善它......

    PT

  • 4

    我提出了一个对我来说非常好的解决方案:

    function shadeColor(color, percent) {
    
        var R = parseInt(color.substring(1,3),16);
        var G = parseInt(color.substring(3,5),16);
        var B = parseInt(color.substring(5,7),16);
    
        R = parseInt(R * (100 + percent) / 100);
        G = parseInt(G * (100 + percent) / 100);
        B = parseInt(B * (100 + percent) / 100);
    
        R = (R<255)?R:255;  
        G = (G<255)?G:255;  
        B = (B<255)?B:255;  
    
        var RR = ((R.toString(16).length==1)?"0"+R.toString(16):R.toString(16));
        var GG = ((G.toString(16).length==1)?"0"+G.toString(16):G.toString(16));
        var BB = ((B.toString(16).length==1)?"0"+B.toString(16):B.toString(16));
    
        return "#"+RR+GG+BB;
    }
    

    示例减轻:

    shadeColor("#63C6FF",40);
    

    示例变暗:

    shadeColor("#63C6FF",-40);
    
  • 0

    我尝试了你的功能并且有一个小错误:如果某些最终'r'值只是1位数,那么结果就像:'a0a0a',例如,正确的值是'0a0a0a' . 我只是通过添加此而不是返回来快速修复它:

    var rStr = (r.toString(16).length < 2)?'0'+r.toString(16):r.toString(16);
    var gStr = (g.toString(16).length < 2)?'0'+g.toString(16):g.toString(16);
    var bStr = (b.toString(16).length < 2)?'0'+b.toString(16):b.toString(16);
    
    return (usePound?"#":"") + rStr + gStr + bStr;
    

    也许这不是那么好,但它做的工作 . 功能强大,BTW . 正是我需要的 . :)

  • 2

    你有没有想过rgb> hsl转换?然后只是上下移动亮度?这就是我要去的方式 .

    快速查看一些算法让我得到以下网站 .

    PHP:http://serennu.com/colour/rgbtohsl.php

    Javascript:http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript

    EDIT 以上链接不再有效 . 你可以查看page sourcegist的git hub

    另外,另一个StackOverflow question可能是个好看的地方 .


    尽管这不是OP的正确选择,但以下是我最初建议的代码的近似值 . (假设你有rgb / hsl转换函数)

    var SHADE_SHIFT_AMOUNT = 0.1; 
    
    function lightenShade(colorValue)
    {
        if(colorValue && colorValue.length >= 6)
        {
            var redValue = parseInt(colorValue.slice(-6,-4), 16);
            var greenValue = parseInt(colorValue.slice(-4,-2), 16);
            var blueValue = parseInt(colorValue.slice(-2), 16);
    
            var hsl = rgbToHsl(redValue, greenValue, blueValue);
            hsl[2]= Math.min(hsl[2] + SHADE_SHIFT_AMOUNT, 1);
            var rgb = hslToRgb(hsl[0], hsl[1], hsl[2]);
            return "#" + rgb[0].toString(16) + rgb[1].toString(16) + rgb[2].toString(16);
        }
        return null;
    }
    
    function darkenShade(colorValue)
    {
        if(colorValue && colorValue.length >= 6)
        {
            var redValue = parseInt(colorValue.slice(-6,-4), 16);
            var greenValue = parseInt(colorValue.slice(-4,-2), 16);
            var blueValue = parseInt(colorValue.slice(-2), 16);
    
            var hsl = rgbToHsl(redValue, greenValue, blueValue);
            hsl[2]= Math.max(hsl[2] - SHADE_SHIFT_AMOUNT, 0);
            var rgb = hslToRgb(hsl[0], hsl[1], hsl[2]);
            return "#" + rgb[0].toString(16) + rgb[1].toString(16) + rgb[2].toString(16);
        }
        return null;
    }
    

    这假定:

    • 您有函数 hslToRgbrgbToHsl .

    • 参数 colorValue#RRGGBB 形式的字符串

    虽然如果我们讨论css,有一种语法可以为IE9 / Chrome / Firefox指定hsl/hsla .

  • 1

    这是我根据你的功能使用的 . 我更喜欢使用超过百分比的步骤,因为它对我来说更直观 .

    例如,200蓝色值的20%与40蓝色值的20%大不相同 .

    无论如何,这是我的修改,感谢您的原始功能 .

    function adjustBrightness(col, amt) {
    
        var usePound = false;
    
        if (col[0] == "#") {
            col = col.slice(1);
            usePound = true;
        }
    
        var R = parseInt(col.substring(0,2),16);
        var G = parseInt(col.substring(2,4),16);
        var B = parseInt(col.substring(4,6),16);
    
        // to make the colour less bright than the input
        // change the following three "+" symbols to "-"
        R = R + amt;
        G = G + amt;
        B = B + amt;
    
        if (R > 255) R = 255;
        else if (R < 0) R = 0;
    
        if (G > 255) G = 255;
        else if (G < 0) G = 0;
    
        if (B > 255) B = 255;
        else if (B < 0) B = 0;
    
        var RR = ((R.toString(16).length==1)?"0"+R.toString(16):R.toString(16));
        var GG = ((G.toString(16).length==1)?"0"+G.toString(16):G.toString(16));
        var BB = ((B.toString(16).length==1)?"0"+B.toString(16):B.toString(16));
    
        return (usePound?"#":"") + RR + GG + BB;
    
    }
    
  • 75

    我想将颜色更改为 specific 亮度等级 - 无论之前的颜色是什么亮度 - 这里's a simple JS function that seems to work well, although I'确定它可以更短

    function setLightPercentage(col: any, p: number) {
        const R = parseInt(col.substring(1, 3), 16);
        const G = parseInt(col.substring(3, 5), 16);
        const B = parseInt(col.substring(5, 7), 16);
        const curr_total_dark = (255 * 3) - (R + G + B);
    
        // calculate how much of the current darkness comes from the different channels
        const RR = ((255 - R) / curr_total_dark);
        const GR = ((255 - G) / curr_total_dark);
        const BR = ((255 - B) / curr_total_dark);
    
        // calculate how much darkness there should be in the new color
        const new_total_dark = ((255 - 255 * (p / 100)) * 3);
    
        // make the new channels contain the same % of available dark as the old ones did
        const NR = 255 - Math.round(RR * new_total_dark);
        const NG = 255 - Math.round(GR * new_total_dark);
        const NB = 255 - Math.round(BR * new_total_dark);
    
        const RO = ((NR.toString(16).length === 1) ? "0" + NR.toString(16) : NR.toString(16));
        const GO = ((NG.toString(16).length === 1) ? "0" + NG.toString(16) : NG.toString(16));
        const BO = ((NB.toString(16).length === 1) ? "0" + NB.toString(16) : NB.toString(16));
    
        return "#" + RO + GO + BO;}
    
  • 0

    C#版本...请注意,我正在以#FF12AE34格式获取颜色字符串,并需要删除#FF .

    private string GetSmartShadeColorByBase(string s, float percent)
        {
            if (string.IsNullOrEmpty(s))
                return "";
            var r = s.Substring(3, 2);
            int rInt = int.Parse(r, NumberStyles.HexNumber);
            var g = s.Substring(5, 2);
            int gInt = int.Parse(g, NumberStyles.HexNumber);
            var b = s.Substring(7, 2);
            int bInt = int.Parse(b, NumberStyles.HexNumber);
    
            var t = percent < 0 ? 0 : 255;
            var p = percent < 0 ? percent*-1 : percent;
    
            int newR = Convert.ToInt32(Math.Round((t - rInt) * p) + rInt);
            var newG = Convert.ToInt32(Math.Round((t - gInt) * p) + gInt);
            var newB = Convert.ToInt32(Math.Round((t - bInt) * p) + bInt);
    
            return String.Format("#{0:X2}{1:X2}{2:X2}", newR, newG, newB);
        }
    
  • 1

    以下方法将允许您使十六进制(十六进制)颜色字符串的曝光值变亮或变暗:

    private static string GetHexFromRGB(byte r, byte g, byte b, double exposure)
    {
        exposure = Math.Max(Math.Min(exposure, 1.0), -1.0);
        if (exposure >= 0)
        {
            return "#"
                + ((byte)(r + ((byte.MaxValue - r) * exposure))).ToString("X2")
                + ((byte)(g + ((byte.MaxValue - g) * exposure))).ToString("X2")
                + ((byte)(b + ((byte.MaxValue - b) * exposure))).ToString("X2");
        }
        else
        {
            return "#"
                + ((byte)(r + (r * exposure))).ToString("X2")
                + ((byte)(g + (g * exposure))).ToString("X2")
                + ((byte)(b + (b * exposure))).ToString("X2");
        }
    
    }
    

    对于GetHexFromRGB()中的最后一个参数值,传入介于-1和1之间的双精度值(-1表示黑色,0表示未更改,1表示白色):

    // split color (#e04006) into three strings
    var r = Convert.ToByte("e0", 16);
    var g = Convert.ToByte("40", 16);
    var b = Convert.ToByte("06", 16);
    
    GetHexFromRGB(r, g, b, 0.25);  // Lighten by 25%;
    
  • 0

    如何在PHP中简单的阴影颜色?

    <?php
    function shadeColor ($color='#cccccc', $percent=-25) {
    
      $color = Str_Replace("#",Null,$color);
    
      $r = Hexdec(Substr($color,0,2));
      $g = Hexdec(Substr($color,2,2));
      $b = Hexdec(Substr($color,4,2));
    
      $r = (Int)($r*(100+$percent)/100);
      $g = (Int)($g*(100+$percent)/100);
      $b = (Int)($b*(100+$percent)/100);
    
      $r = Trim(Dechex(($r<255)?$r:255));  
      $g = Trim(Dechex(($g<255)?$g:255));  
      $b = Trim(Dechex(($b<255)?$b:255));
    
      $r = ((Strlen($r)==1)?"0{$r}":$r);
      $g = ((Strlen($g)==1)?"0{$g}":$g);
      $b = ((Strlen($b)==1)?"0{$b}":$b);
    
      return (String)("#{$r}{$g}{$b}");
    }
    
    echo shadeColor(); // #999999
    
  • 798

    我创建了一个优秀的xcolor库的端口来删除它的jQuery依赖项 . 那里有很多功能,包括闪电和变暗的颜色 .

    实际上,将十六进制转换为RGB是一种完全独立的功能,可以使颜色变亮或变暗 . 请保持干燥 . 无论如何,一旦你如果你有RGB颜色,你可以添加你想要的光照水平和你对每个RGB值的光照水平之间的差异:

    var lightness = function(level) {
        if(level === undefined) {
            return Math.max(this.g,this.r,this.b)
        } else {
            var roundedLevel = Math.round(level) // fractions won't work here
            var levelChange = roundedLevel - this.lightness()
    
            var r = Math.max(0,this.r+levelChange)
            var g = Math.max(0,this.g+levelChange)
            var b = Math.max(0,this.b+levelChange)
    
            if(r > 0xff) r = 0xff
            if(g > 0xff) g = 0xff
            if(b > 0xff) b = 0xff
    
            return xolor({r: r, g: g, b: b})
        }
    }
    
    var lighter = function(amount) {
        return this.lightness(this.lightness()+amount)
    }
    

    有关更多信息源,请参阅https://github.com/fresheneesz/xolor .

  • 3

    我一直希望能够产生色彩/色调,这是我的JavaScript解决方案:

    const varyHue = function (hueIn, pcIn) {
        const truncate = function (valIn) {
            if (valIn > 255) {
                valIn = 255;
            } else if (valIn < 0)  {
                valIn = 0;
            }
            return valIn;
        };
    
        let red   = parseInt(hueIn.substring(0, 2), 16);
        let green = parseInt(hueIn.substring(2, 4), 16);
        let blue  = parseInt(hueIn.substring(4, 6), 16);
        let pc    = parseInt(pcIn, 10);    //shade positive, tint negative
        let max   = 0;
        let dif   = 0;
    
        max = red;
    
        if (pc < 0) {    //tint: make lighter
            if (green < max) {
                max = green;
            }
    
            if (blue < max) {
                max = blue;
            }
    
            dif = parseInt(((Math.abs(pc) / 100) * (255 - max)), 10);
    
            return leftPad(((truncate(red + dif)).toString(16)), '0', 2)  + leftPad(((truncate(green + dif)).toString(16)), '0', 2) + leftPad(((truncate(blue + dif)).toString(16)), '0', 2);
        } else {    //shade: make darker
            if (green > max) {
                max = green;
            }
    
            if (blue > max) {
                max = blue;
            }
    
            dif = parseInt(((pc / 100) * max), 10);
    
            return leftPad(((truncate(red - dif)).toString(16)), '0', 2)  + leftPad(((truncate(green - dif)).toString(16)), '0', 2) + leftPad(((truncate(blue - dif)).toString(16)), '0', 2);
        }
    };
    

相关问题