以编程方式增亮或减淡hex颜色(或rgb,并混合颜色)

这是一个函数,我正在努力程序化按照特定的数量减淡或加深hex颜色。 只需要传递一个像“3F6D2A”这样的颜色(col)和一个base10整数(amt)的string来让数量变亮或变暗。 要变暗,通过一个负数(即-20)。

我之所以这样做,是因为我发现的所有解决scheme,到目前为止,似乎使问题过度复杂化。 而且我感觉只需要几行代码就可以完成。 请让我知道,如果你发现任何问题,或作出任何调整,使其加快。

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); 

我想我的主要问题是,我在这里纠正? 这是否包含一些(正常的)情况?

TL; DR? – 简单的减轻/变暗(阴影)? 跳到第2版,select一个RGB或hex。 – 想要一个全function的着色器/搅拌器/转换器与错误检查和阿尔法和3位hex? 使用版本3附近的底部。

玩3版: http : //www.pimptrizkit.com/?t=20%20Shades


经过一番思考……我决定回答我自己的问题。 一年半后。 这真是一个冒险与来自几个有用的用户的想法,我感谢你们所有! 这个是给团队的! 虽然它不一定是我正在寻找的答案。 因为如果James Khoury说的是真的,那么在javascript中就没有真正的hexmath,我必须使用小数,这个双重转换是必要的。 如果我们做这个假设,那么这可能是我看到(或可以想到)以百分比减轻(增加白色)或变黑(增加黑色)任意RBG颜色的最快方式。 这也解释了冷酸在他对这个问题的答案中提到的问题(它填充0)。 但是这个版本只调用一次toString 。 这也是超出范围(它将强制执行0和255作为限制)。

但要小心,颜色input必须是正确的7个字符,如#08a35c 。 (如果使用顶级版本,则为6)

感谢Pablo提供使用百分比的灵感和想法。 为此,我将保持函数名称相同! 大声笑! 然而,这一点是不同的,因为它将百分比标准化为255,从而为每种颜色(更白)添加相同的数量。 如果你通过百分之百,它会使你的颜色纯白。 如果你通过percent 0,什么都不会发生。 如果您通过percent 1,则会为所有颜色添加3个阴影(每1%有2.55个阴影,圆整)。 所以你真的在白色(或黑色,使用负面)的百分比传递。 所以,这个版本可以让你减轻纯红色(FF0000)。

我也使用Keith Mashinter对这个问题的回答: 如何在JavaScript中将十进制转换为hex?

我删除了一些,似乎是不必要的括号。 (就像在二元三元语句和G中一样)不确定这是否会在某些环境中扰乱运算符的优先级。 testing好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!

– 更新 – 版本2与混合 –

一年多一点,再一次,还在继续。 但是这一次我认为它完成了。 注意到关于不使用HSL来正确减轻颜色的问题。 有一种技术可以消除大部分的不准确性,而不必转换成HSL。 主要的问题是在颜色的其余部分之前,颜色通道会完全饱和。 在这之后引起色调的变化。 我在 这里和这里发现了这些问题,使我走上正轨。 Mark Ransom的post向我展示了不同之处, Keith的post告诉了我。 莱普是救世主。 这和混合颜色是一样的,所以我也创build了一个blendColors函数。


TL; DR – 为了简单的shadeColor2 /变暗,使用下面的这个函数shadeColor2 。 或者它的RGB对应的shadeRGBColor RGB进一步下面,给我一票。 但是,如果你想要任何和/或所有的好东西。 如同时使用RGB和Hex颜色,错误检测,3位hex解码,混合,Alpha通道和RGB2Hex / Hex2RGB转换的能力。 然后,跳到第3版的shadeBlendConvert得到所有的花里胡哨和给我两票。 如果需要,您可以删除几行以删除其中一些function。 如果您记得上面的版本1 shadeColor1已被弃用所有用途,您会得到一票。


所以,没有进一步的道理:

– 版本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((tR)*p)+R)*0x10000+(Math.round((tG)*p)+G)*0x100+(Math.round((tB)*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); } 

更进一步:

没有错误检查,所以传入的值超出范围将导致意想不到的结果。 另外,颜色input必须是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慢,但不是一个值得注意的量。 (等等,这是一个自相矛盾的说法!)

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

– 版本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((tR)*p)+R)+","+(Math.round((tG)*p)+G)+","+(Math.round((tB)*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) 

– 版本2通用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); 

– 版本2通用B –

好的! 这个答案的普及让我觉得我可以做一个更好的通用版本。 所以,你去! 该版本是RGB和Hex色彩的全function复制/粘贴着色器/混合器。 这个与上面提供的其他Uni版本没有任何区别。 除了它小得多的function粘贴和使用。 如果将它压缩成一行,我认为大小从大约1592个字符变为557个字符。 当然,如果你不需要在RGB和Hex之间交换使用它,那么你不需要像这样的通用版本。 只要使用上面更小更快的版本之一, 适合你的配色scheme。 继续…在某些方面,它稍微快一点,在某些方面稍微慢一些。 我没有做任何最终的速度testing分析。 有两种用法上的区别:第一,百分比现在是函数的第一个参数,而不是最后一个。 其次,混合时,可以使用负数。 他们只会被转换成正数。

再也不用说了:

 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 

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

* V2其他语言*

– Swift Extension – RGB (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 = (tr)*p+r g = (tg)*p+g b = (tb)*p+b return UIColor(red: r, green: g, blue: b, alpha: a) } } 

– PHP版本 – HEX (作者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); } 

– 更新 – 版本3通用 –

几个月后,自上次通用版以来还有一年的时间。 所以……感谢sricks的深刻见解。 我决定再次把它提升到一个新的水平。 它不再是两线速度恶魔,因为它已经开始了,哈哈。 但是,它所做的却是相当快,很小。 它的1249字节,如果你压缩它(一行,没有白人,单个字符var名称)。 如果你另外删除ErrorChecking并删除3位解码,你可以把它降到955字节,更快。 这在1K以下是很大的力量。 试想一下,你可以把它加载到一个Commodore64上,而且还有63个空间! (不考虑JavaScript引擎大于63k的事实)

显然有更多的事情要做:

 function shadeBlendConvert(p, from, to) { if(typeof(p)!="number"||p<-1||p>1||typeof(from)!="string"||(from[0]!='r'&&from[0]!='#')||(typeof(to)!="string"&&typeof(to)!="undefined"))return null; //ErrorCheck if(!this.sbcRip)this.sbcRip=(d)=>{ let l=d.length,RGB=new Object(); if(l>9){ d=d.split(","); if(d.length<3||d.length>4)return null;//ErrorCheck RGB[0]=i(d[0].slice(4)),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 digit d=i(d.slice(1),16),RGB[0]=d>>16&255,RGB[1]=d>>8&255,RGB[2]=d&255,RGB[3]=l==9||l==5?r(((d>>24&255)/255)*10000)/10000:-1; } 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("+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+(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)*0x1000000+r((t[0]-f[0])*p+f[0])*0x10000+r((t[1]-f[1])*p+f[1])*0x100+r((t[2]-f[2])*p+f[2])).toString(16).slice(f[3]>-1||t[3]>-1?1:3); } 

玩3版: http : //www.pimptrizkit.com/?t=20%20Shades

这个版本的核心math和以前一样。 但是,我做了一些重大的重构。 这实现了更多的function和控制。 它现在固有地转换RGB2Hex和Hex2RGB。

上面v2的所有旧function仍然在这里。 我试图testing一切,如果你发现任何错误,请发表评论。 无论如何,这里是新的function:

  • 接受3位(或4位)HEX颜色代码,格式为#RGB(或#ARGB)。 它会扩大他们。 删除标有//3 digit以删除此function。
  • 接受并混合alpha通道。 如果from颜色或颜色有一个alpha通道,那么结果将有一个alpha通道。 如果两种颜色都有一个alpha通道,则结果将是使用给定百分比的两个alpha通道的混合(就像它是一个正常的颜色通道一样)。 如果两种颜色中只有一种具有alpha通道,那么这个alpha就会直接传递给结果。 这允许在保持透明水平的同时混合/遮蔽透明颜色。 或者,如果透明层次也应该混合,确保两种颜色都有alpha。 如果你想要基本阴影也可以混合alpha通道,则使用rgb(0,0,0,1)rgb(255,255,255,1)作为颜色(或它们的hex等价物)。 对于RGB颜色,生成的alpha通道将四舍五入到小数点后4位。
  • 使用混合时,RGB2Hex和Hex2RGB转换现在是隐含的。 如果存在的话,结果颜色总是to颜色的forms出现。 如果没有颜色,则将'c'作为颜色传递,然后to阴影转换。 如果只需要转换,则也将百分比传递给0
  • 全球也增加了一个辅助function。 sbcRip可以传递一个hex或rbg颜色,并返回一个包含这个颜色信息的对象。 其forms为: {0:R,1:G,2:B,0.3:A} 。 其中R GB的范围是0255 。 而当没有alpha时: A-1 。 否则: A的范围是0.00001.0000
  • 轻微错误检查已被添加。 这并不完美。 它仍然可以崩溃。 但它会抓住一些东西。 基本上,如果结构在某些方面是错误的,或者如果百分比不是数字或超出范围,它将返回null 。 例如: shadeBlendConvert(0.5,"salt") = null ,因为它认为#salt是一个有效的颜色。 删除标有//ErrorCheck四行以删除此function。

用途:

 var color1 = "rgb(114,93,20)"; var color2 = "rgb(114,93,20,0.37423)"; var color3 = "#67DAF0"; var color4 = "#5567DAF0"; var color5 = "#F3A"; var color6 = "#DF3A"; var color7 = "rgb(75,200,112)"; var color8 = "rgb(75,200,112,0.98631)"; var c; // Shade (Lighten or Darken) c = shadeBlendConvert(0.3,color1); // rgb(114,93,20) + [30% Lighter] => rgb(156,142,91) c = shadeBlendConvert(-0.13,color5); // #F3A + [13% Darker] => #de2c94 // Shade with Conversion (use 'c' as your 'to' color) c = shadeBlendConvert(0.42,color2,"c"); //rgb(114,93,20,0.37423) + [42% Lighter] + [Convert] => #5fada177 // RGB2Hex & Hex2RGB Conversion Only (set percentage to zero) c = shadeBlendConvert(0,color6,"c"); // #DF3A + [Convert] => rgb(255,51,170,0.8667) // Blending c = shadeBlendConvert(-0.13,color2,color8); // rgb(114,93,20,0.37423) + rgb(75,200,112,0.98631) + [13% Blend] => rgb(109,107,32,0.4538) c = shadeBlendConvert(0.65,color2,color7); // rgb(114,93,20,0.37423) + rgb(75,200,112) + [65% Blend] => rgb(89,163,80,0.37423) // Blending with Conversion (result is in the 'to' color format) c = shadeBlendConvert(0.3,color1,color3); // rgb(114,93,20) + #67DAF0 + [30% Blend] + [Convert] => #6f8356 c = shadeBlendConvert(-0.13,color4,color2); // #5567DAF0 + rgb(114,93,20,0.37423) + [13% Blend] + [Convert] => rgb(104,202,211,0.3386) // Error Checking c = shadeBlendConvert(0.3,"#FFBAA"); // #FFBAA + [30% Lighter] => null c = shadeBlendConvert(30,color1,color5); // rgb(114,93,20) + #F3A + [3000% Blend] => null // A pound of salt is jibberish (Error Check Fail) c = shadeBlendConvert(0.3,"#salt"); // #salt + [30% Lighter] => #004d4d4d // Ripping c = sbcRip(color4); // #5567DAF0 + [Rip] =>> {0:103,1:218,2:240,3:0.3333} 

我现在毫不犹豫地把这个做完了…

PT

– EDIT:切换版本3使用let和一个箭头函数,并将其添加到sbcRip调用。

我提出了一个对我非常好的解决scheme:

 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); 

我尝试了你的函数,并且有一个小错误:如果最后一个'r'的值只有一个数字,结果就是:'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; 

也许这不是很好,但它做的工作。 很棒的function,BTW。 正是我所需要的。 🙂

你有没有想过一个rgb> hsl转换? 那么就把光度上下移动吧? 那就是我会走的路。

快速查找一些algorithm让我下面的网站。

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

编辑上面的链接不再有效。 你可以查看页面源码或要点的 git hub

或者另一个StackOverflow 问题可能是一个很好的地方。


即使这不是OP的正确select,以下是我最初build议的代码的近似值。 (假设你有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; } 

这假定:

  1. 你有函数hslToRgbrgbToHsl
  2. 参数colorValue是格式为#RRGGBB的string

虽然如果我们正在讨论的CSS有一个语法为IE9 / Chrome / Firefox指定hsl / hsla 。

C#版本…请注意,我得到这种格式的颜色string#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); } 

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

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

无论如何,这是我的修改,感谢您的原始function。

 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); 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; } 

以下方法将允许您减淡或加深hex颜色string:

 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"); } } 

传入-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%; 

如何在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 

我做了一个优秀的xcolor库的端口,以消除其jQuery的依赖。 那里有很多的function,包括减轻和变暗的颜色。

真的,将hex转换为RGB是一个完全独立的function,从减轻或变暗的颜色。 请保持干爽。 在任何情况下,一旦你有一个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) } 

See https://github.com/fresheneesz/xolor for more of the source.

I've long wanted to be able to produce tints/shades of colours, here is my JavaScript solution:

 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); } };