Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
604 views
in Technique[技术] by (71.8m points)

javascript - 以编程方式使十六进制颜色(或rgb和混合颜色)变亮或变暗(Programmatically Lighten or Darken a hex color (or rgb, and blend colors))

Here is a function I was working on to programmatically lighten or darken a hex color by a specific amount.

(这是我正在使用的功能,用于以编程方式使十六进制颜色变亮或变暗特定数量。)

Just pass in a string like "3F6D2A" for the color ( col ) and a base10 integer ( amt ) for the amount to lighten or darken.

(只需输入一个类似"3F6D2A"的字符串作为颜色( col )和一个以10为底的整数( amt )作为变亮或变暗的量。)

To darken, pass in a negative number (ie -20).

(要变暗,请输入负数(即-20)。)

The reason for me to do this was because of all the solutions I found, thus far, they seemed to over-complicate the issue.

(我这样做的原因是因为我找到了所有解决方案,到目前为止,它们似乎使问题变得过于复杂。)

And I had a feeling it could be done with just a couple lines of code.

(我觉得只需几行代码就可以完成。)

Please let me know if you find any problems, or have any adjustments to make that would speed it up.

(如果您发现任何问题或进行任何调整以加快速度,请告诉我。)

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

For Development use here is an easier to read version:

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

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

And finally a version to handle colors that may (or may not) have the "#" in the beginning.

(最后是处理可能(或可能没有)开头带有“#”的颜色的版本。)

Plus adjusting for improper color values:

(加上调整不正确的颜色值:)

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

OK, so now it's not just a couple of lines, but it seems far simpler and if you're not using the "#" and don't need to check for colors out of range, it is only a couple of lines.

(好的,所以现在它不仅是几行,而且看起来要简单得多,如果您不使用“#”并且不需要检查颜色是否超出范围,则只需几行。)

If not using the "#", you can just add it in code like:

(如果不使用“#”,则可以将其添加到以下代码中:)

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

I guess my main question is, am I correct here?

(我想我的主要问题是,我在这里正确吗?)

Does this not encompass some (normal) situations?

(这不包括某些(正常)情况吗?)

  ask by Pimp Trizkit translate from so

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Well, this answer has become its own beast.

(好吧,这个答案已经变成了自己的野兽。)

Many new versions, it was getting stupid long.

(许多新版本,它变得愚蠢了很长时间。)

Many thanks to all of the great many contributors to this answer.

(非常感谢对此答案做出的所有贡献。)

But, in order to keep it simple for the masses.

(但是,为了使它简单易行。)

I archived all the versions/history of this answer's evolution to my github .

(我将该答案的所有版本/历史记录存档到github中)

And started it over clean on StackOverflow here with the newest version.

(并以最新版本在StackOverflow上重新启动。)

A special thanks goes out to Mike 'Pomax' Kamermans for this version.

(特别感谢Mike'Pomax'Kamermans这个版本。)

He gave me the new math.

(他给了我新的数学。)


This function ( pSBC ) will take a HEX or RGB web color.

(此功能( pSBC )将采用十六进制或RGB网页颜色。)

pSBC can shade it darker or lighter, or blend it with a second color, and can also pass it right thru but convert from Hex to RGB (Hex2RGB) or RGB to Hex (RGB2Hex).

(pSBC可以使它变暗或变亮,或将其与第二种颜色混合,也可以将其直接传递但从Hex转换为RGB(Hex2RGB)或从RGB转换为Hex(RGB2Hex)。)

All without you even knowing what color format you are using.

(所有这些甚至都不知道您使用的是哪种颜色格式。)

This runs really fast, probably the fastest, especially considering its many features.

(这运行得非常快,可能是最快的,特别是考虑到它的许多功能。)

It was a long time in the making.

(制作时间很长。)

See the whole story on my github .

(在我的github上查看整个故事。)

If you want the absolutely smallest and fastest possible way to shade or blend, see the Micro Functions below and use one of the 2-liner speed demons.

(如果要使用绝对最小和最快的方式着色或混合,请参阅下面的微功能并使用2线速度恶魔之一。)

They are great for intense animations, but this version here is fast enough for most animations.

(它们非常适合用于激烈的动画,但是此处的此版本对于大多数动画而言足够快。)

This function uses Log Blending or Linear Blending.

(此功能使用对数混合或线性混合。)

However, it does NOT convert to HSL to properly lighten or darken a color.

(但是,它不能转换为HSL来适当地使颜色变暗或变暗。)

Therefore, results from this function will differ from those much larger and much slower functions that use HSL.

(因此, 此函数的结果将不同于使用HSL的更大,更慢的函数。)

jsFiddle with pSBC

(jsFiddle与pSBC)

github > pSBC Wiki

(github> pSBC维基)

Features:

(特征:)

  • Auto-detects and accepts standard Hex colors in the form of strings.

    (自动检测并接受字符串形式的标准十六进制颜色。)

    For example: "#AA6622" or "#bb551144" .

    (例如: "#AA6622""#bb551144" 。)

  • Auto-detects and accepts standard RGB colors in the form of strings.

    (自动检测并接受字符串形式的标准RGB颜色。)

    For example: "rgb(123,45,76)" or "rgba(45,15,74,0.45)" .

    (例如: "rgb(123,45,76)""rgba(45,15,74,0.45)" 。)

  • Shades colors to white or black by percentage.

    (按百分比将颜色着色为白色或黑色。)

  • Blends colors together by percentage.

    (按百分比将颜色混合在一起。)

  • Does Hex2RGB and RGB2Hex conversion at the same time, or solo.

    (Hex2RGB和RGB2Hex是否同时或单独转换。)

  • Accepts 3 digit (or 4 digit w/ alpha) HEX color codes, in the form #RGB (or #RGBA).

    (接受格式为#RGB(或#RGBA)的3位数(或4位数,带alpha)十六进制颜色代码。)

    It will expand them.

    (它将扩展它们。)

    For Example: "#C41" becomes "#CC4411" .

    (例如: "#C41"变为"#CC4411" 。)

  • Accepts and (Linear) blends alpha channels.

    (接受和(线性)混合Alpha通道。)

    If either the c0 (from) color or the c1 (to) color has an alpha channel, then the returned color will have an alpha channel.

    (如果c0 (从)颜色或c1 (到)颜色具有alpha通道,则返回的颜色将具有alpha通道。)

    If both colors have an alpha channel, then the returned color will be a linear blend of the two alpha channels using the percentage given (just as if it were a normal color channel).

    (如果两种颜色都具有一个Alpha通道,则返回的颜色将使用给定的百分比是两个Alpha通道的线性混合(就像它是普通颜色通道一样)。)

    If only one of the two colors has an alpha channel, this alpha will just be passed thru to the returned color.

    (如果两种颜色中只有一种具有Alpha通道,则该Alpha会直接传递到返回的颜色。)

    This allows one to blend/shade a transparent color while maintaining the transparency level.

    (这样可以在保持透明度级别的同时混合/着色透明颜色。)

    Or, if the transparency levels should blend as well, make sure both colors have alphas.

    (或者,如果透明度级别也要混合,请确保两种颜色都具有Alpha。)

    When shading, it will pass the alpha channel straight thru.

    (着色时,它将直接通过Alpha通道。)

    If you want basic shading that also shades the alpha channel, then use rgb(0,0,0,1) or rgb(255,255,255,1) as your c1 (to) color (or their hex equivalents).

    (如果您希望基本着色也可以使Alpha通道着色,请使用rgb(0,0,0,1)rgb(255,255,255,1)作为c1 (至)颜色(或其十六进制等效项)。)

    For RGB colors, the returned color's alpha channel will be rounded to 3 decimal places.

    (对于RGB颜色,返回的颜色的alpha通道将四舍五入到小数点后三位。)

  • RGB2Hex and Hex2RGB conversions are implicit when using blending.

    (使用混合时,RGB2Hex和Hex2RGB转换是隐式的。)

    Regardless of the c0 (from) color;

    (不论c0 (来自)颜色;)

    the returned color will always be in the color format of the c1 (to) color, if one exists.

    (如果存在,返回的颜色将始终为c1 (至)颜色的颜色格式。)

    If there is no c1 (to) color, then pass 'c' in as the c1 color and it will shade and convert whatever the c0 color is.

    (如果没有c1 (至)颜色,则将'c'作为c1颜色传递,它将着色并转换为c0颜色。)

    If conversion only is desired, then pass 0 in as the percentage ( p ) as well.

    (如果仅需要转换,则也将0作为百分比( p )传递。)

    If the c1 color is omitted or a falsy is passed in, it will not convert.

    (如果省略c1颜色或传入错误,则不会转换。)

  • A secondary function is added to the global as well.

    (辅助功能也被添加到全局中。)

    pSBCr can be passed a Hex or RGB color and it returns an object containing this color information.

    (可以将十六进制或RGB颜色传递给pSBCr ,并返回包含该颜色信息的对象。)

    Its in the form: {r: XXX, g: XXX, b: XXX, a: X.XXX}.

    (其格式为:{r:XXX,g:XXX,b:XXX,a:X.XXX}。)

    Where .r , .g , and .b have range 0 to 255. And when there is no alpha: .a is -1.

    (其中.r.g.b范围为0到255。并且当没有alpha时: .a为-1。)

    Otherwise: .a has range 0.000 to 1.000.

    (否则: .a范围是0.000到1.000。)

  • For RGB output, it outputs rgba() over rgb() when a color with an alpha channel was passed into c0 (from) and/or c1 (to).

    (对于RGB输出,当具有alpha通道的颜色传递到c0 (从)和/或c1 (到)时,它将在rgb()输出rgba() )。)

  • Minor Error Checking has been added.

    (轻微错误检查已添加。)

    It's not perfect.

    (这不是完美的。)

    It can still crash or create jibberish.

    (它仍然可能崩溃或产生乱码。)

    But it will catch some stuff.

    (但是,它将捕获一些东西。)

    Basically, if the structure is wrong in some ways or if the percentage is not a number or out of scope, it will return null .

    (基本上,如果结构在某些方面是错误的,或者百分比不是数字或超出范围,则它将返回null 。)

    An example: pSBC(0.5,"salt") == null , where as it thinks #salt is a valid color.

    (一个示例: pSBC(0.5,"salt") == null ,因为它认为#salt是有效颜色。)

    Delete the four lines which end with return null;

    (删除以return null;结尾的四行return null;)

    to remove this feature and make it faster and smaller.

    (删除此功能并使其更快,更小。)

  • Uses Log Blending.

    (使用日志混合。)

    Pass true in for l (the 4th parameter) to use Linear Blending.

    (在l传递true (第4个参数)以使用线性混合。)

Code:(码:)

// Version 4.0
const pSBC=(p,c0,c1,l)=>{
    let r,g,b,P,f,t,h,i=parseInt,m=Math.round,a=typeof(c1)=="string";
    if(typeof(p)!="number"||p<-1||p>1||typeof(c0)!="string"||(c0[0]!='r'&&c0[0]!='#')||(c1&&!a))return null;
    if(!this.pSBCr)this.pSBCr=(d)=>{
        let n=d.length,x={};
        if(n>9){
            [r,g,b,a]=d=d.split(","),n=d.length;
            if(n<3||n>4)return null;
            x.r=i(r[3]=="a"?r.slice(5):r.slice(4)),x.g=i(g),x.b=i(b),x.a=a?parseFloat(a):-1
        }else{
            if(n==8||n==6||n<4)return null;
            if(n<6)d="#"+d[1]+d[1]+d[2]+d[2]+d[3]+d[3]+(n>4?d[4]+d[4]:"");
            d=i(d.slice(1),16);
            if(n==9||n==5)x.r=d>>24&255,x.g=d>>16&255,x.b=d>>8&255,x.a=m((d&255)/0.255)/1000;
            else x.r=d>>16,x.g=d>>8&255,x.b=d&255,x.a=-1
        }return x};
    h=c0.length>9,h=a?c1.length>9?true:c1=="c"?!h:false:h,f=this.p

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...