【问题标题】:Programmatically Lighten or Darken a hex color (or rgb, and blend colors)以编程方式使十六进制颜色变亮或变暗(或 rgb 和混合颜色)
【发布时间】:2018-12-23 18:17:20
【问题描述】:

这是我正在开发的一个函数,它可以通过编程将十六进制颜色变亮或变暗特定量。只需传入一个类似"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);
}


// TEST
console.log( LightenDarkenColor("3F6D2A",40) );

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

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


// TEST
console.log(LightenDarkenColor("3F6D2A", -40));

最后一个版本可以处理开头可能(或可能没有)带有“#”的颜色。加上调整不正确的颜色值:

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

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

【问题讨论】:

  • 如果你在修改颜色的时候没有得到预期的结果,我建议你研究一下更接近人类视觉的 LAB 颜色空间。许多语言都有用于转换的库。根据我的经验,尤其是橙色阴影在变暗或变亮时可能会出现问题。
  • 非常好。但是,这个问题的主要目的是首先找到最快的运行时间和最小的公式......其次,它的准确性。因此,为什么我不处理转换为 HSL 或其他问题。这里速度和大小更重要。但是,正如您在我的公式 2 中看到的那样。使用 LERP 进行遮光将在整个遮光范围内产生令人愉悦的橙色。看看下面的颜色图表,让我知道阴影范围是否非常接近实际准确度。
  • 我对这里的结构有点困惑,但你是对的,shadeColor1 的橙色水平似乎非常好。
  • 大声笑,你的意思是 shadeColor2。我猜你所说的结构是答案本身的整体布局?有什么提示可以更清楚吗?
  • 上面的#函数中只有一个问题是,如果最终的十六进制代码以零开头,它不会创建前导零。例如,如果十六进制代码是#00a6b7,它将输出为#a6b7,如果用作css,它将不起作用。您可以通过将返回行替换为: var string = "000000" + (g | (b

标签: javascript colors hex


【解决方案1】:

嗯,这个答案已经变成了自己的野兽。许多新版本,它变得越来越愚蠢。非常感谢所有对此答案的众多贡献者。但是,为了让大众保持简单。我将此答案演变的所有版本/历史存档到我的github。并在 StackOverflow 上使用最新版本重新开始。特别感谢 Mike 'Pomax' Kamermans 提供此版本。他给了我新的数学。


此函数 (pSBC) 将采用 HEX 或 RGB 网络颜色。 pSBC 可以将其着色得更深或更浅,或者将其与第二种颜色混合,也可以将其直接传递,但将其从十六进制转换为 RGB (Hex2RGB) 或从 RGB 转换为十六进制 (RGB2Hex)。您甚至都不知道您使用的是什么颜色格式。

这运行得非常快,可能是最快的,尤其是考虑到它的许多功能。这是一个很长的时间。在我的github 上查看整个故事。如果您想要绝对最小和最快的着色或混合方式,请参阅下面的微功能并使用 2 线速度恶魔之一。它们非常适合制作激烈的动画,但这里的这个版本对于大多数动画来说已经足够快了。

此函数使用对数混合或线性混合。但是,它不会转换为 HSL 以适当地使颜色变亮或变暗。因此,此函数的结果将不同于使用 HSL 的那些更大、更慢的函数。

jsFiddle with pSBC

github > pSBC Wiki

特点:

  • 自动检测并接受字符串形式的标准十六进制颜色。例如:"#AA6622""#bb551144"
  • 自动检测并接受字符串形式的标准 RGB 颜色。例如:"rgb(123,45,76)""rgba(45,15,74,0.45)"
  • 按百分比将颜色渐变为白色或黑色。
  • 按百分比混合颜色。
  • Hex2RGB 和 RGB2Hex 是同时转换还是单独转换。
  • 接受 3 位(或 4 位带 alpha 的)十六进制颜色代码,格式为 #RGB(或 #RGBA)。它将扩展它们。例如:"#C41" 变为 "#CC4411"
  • 接受和(线性)混合 Alpha 通道。如果c0 (from) 颜色或c1 (to) 颜色具有 Alpha 通道,则返回的颜色将具有 Alpha 通道。如果两种颜色都有一个 alpha 通道,则返回的颜色将是使用给定百分比的两个 alpha 通道的线性混合(就像它是一个正常的颜色通道一样)。如果两种颜色中只有一种具有 alpha 通道,则此 alpha 将直接传递给返回的颜色。这允许在保持透明度级别的同时混合/着色透明颜色。或者,如果透明度级别也应该混合,请确保两种颜色都有 alpha。着色时,它将直接通过 Alpha 通道。如果您想要同时对 Alpha 通道进行着色的基本着色,则使用 rgb(0,0,0,1)rgb(255,255,255,1) 作为您的 c1(to)颜色(或它们的十六进制等效项)。对于 RGB 颜色,返回颜色的 alpha 通道将四舍五入到小数点后 3 位。
  • RGB2Hex 和 Hex2RGB 转换在使用混合时是隐式的。无论c0(来自)颜色如何;返回的颜色将始终采用c1(to)颜色的颜色格式(如果存在)。如果没有c1(to)颜色,则将'c'作为c1颜色传入,它将着色并转换c0颜色。如果只需要转换,则也将0 作为百分比 (p) 传入。如果c1颜色被省略或传入非string,则不会转换。
  • 辅助函数也被添加到全局中。 pSBCr 可以传递一个 Hex 或 RGB 颜色,它返回一个包含此颜色信息的对象。格式为:{r: XXX, g: XXX, b: XXX, a: X.XXX}。其中.r.g.b 的范围为0 到255。当没有alpha 时:.a 为-1。否则:.a 的范围为 0.000 到 1.000。
  • 对于 RGB 输出,当带有 Alpha 通道的颜色被传递到 c0(来自)和/或 c1(至)时,它会在 rgb() 上输出 rgba()
  • 已添加小错误检查。这并不完美。它仍然可能崩溃或产生乱码。但它会抓住一些东西。基本上,如果结构在某些方面是错误的,或者百分比不是数字或超出范围,它将返回null。一个例子:pSBC(0.5,"salt") == null,它认为#salt 是一个有效的颜色。删除以return null; 结尾的四行以删除此功能并使其更快更小。
  • 使用日志混合。将true 传递给l(第4 个参数)以使用线性混合。

代码:

// 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.pSBCr(c0),P=p<0,t=c1&&c1!="c"?this.pSBCr(c1):P?{r:0,g:0,b:0,a:-1}:{r:255,g:255,b:255,a:-1},p=P?p*-1:p,P=1-p;
    if(!f||!t)return null;
    if(l)r=m(P*f.r+p*t.r),g=m(P*f.g+p*t.g),b=m(P*f.b+p*t.b);
    else r=m((P*f.r**2+p*t.r**2)**0.5),g=m((P*f.g**2+p*t.g**2)**0.5),b=m((P*f.b**2+p*t.b**2)**0.5);
    a=f.a,t=t.a,f=a>=0||t>=0,a=f?a<0?t:t<0?a:a*P+t*p:0;
    if(h)return"rgb"+(f?"a(":"(")+r+","+g+","+b+(f?","+m(a*1000)/1000:"")+")";
    else return"#"+(4294967296+r*16777216+g*65536+b*256+(f?m(a*255):0)).toString(16).slice(1,f?undefined:-2)
}

用法:

// Setup:

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

// Tests:

/*** Log Blending ***/
// Shade (Lighten or Darken)
pSBC ( 0.42, color1 ); // rgb(20,60,200) + [42% Lighter] => rgb(166,171,225)
pSBC ( -0.4, color5 ); // #F3A + [40% Darker] => #c62884
pSBC ( 0.42, color8 ); // rgba(200,60,20,0.98631) + [42% Lighter] => rgba(225,171,166,0.98631)

// Shade with Conversion (use "c" as your "to" color)
pSBC ( 0.42, color2, "c" ); // rgba(20,60,200,0.67423) + [42% Lighter] + [Convert] => #a6abe1ac

// RGB2Hex & Hex2RGB Conversion Only (set percentage to zero)
pSBC ( 0, color6, "c" ); // #F3A9 + [Convert] => rgba(255,51,170,0.6)

// Blending
pSBC ( -0.5, color2, color8 ); // rgba(20,60,200,0.67423) + rgba(200,60,20,0.98631) + [50% Blend] => rgba(142,60,142,0.83)
pSBC ( 0.7, color2, color7 ); // rgba(20,60,200,0.67423) + rgb(200,60,20) + [70% Blend] => rgba(168,60,111,0.67423)
pSBC ( 0.25, color3, color7 ); // #67DAF0 + rgb(200,60,20) + [25% Blend] => rgb(134,191,208)
pSBC ( 0.75, color7, color3 ); // rgb(200,60,20) + #67DAF0 + [75% Blend] => #86bfd0

/*** Linear Blending ***/
// Shade (Lighten or Darken)
pSBC ( 0.42, color1, false, true ); // rgb(20,60,200) + [42% Lighter] => rgb(119,142,223)
pSBC ( -0.4, color5, false, true ); // #F3A + [40% Darker] => #991f66
pSBC ( 0.42, color8, false, true ); // rgba(200,60,20,0.98631) + [42% Lighter] => rgba(223,142,119,0.98631)

// Shade with Conversion (use "c" as your "to" color)
pSBC ( 0.42, color2, "c", true ); // rgba(20,60,200,0.67423) + [42% Lighter] + [Convert] => #778edfac

// RGB2Hex & Hex2RGB Conversion Only (set percentage to zero)
pSBC ( 0, color6, "c", true ); // #F3A9 + [Convert] => rgba(255,51,170,0.6)

// Blending
pSBC ( -0.5, color2, color8, true ); // rgba(20,60,200,0.67423) + rgba(200,60,20,0.98631) + [50% Blend] => rgba(110,60,110,0.83)
pSBC ( 0.7, color2, color7, true ); // rgba(20,60,200,0.67423) + rgb(200,60,20) + [70% Blend] => rgba(146,60,74,0.67423)
pSBC ( 0.25, color3, color7, true ); // #67DAF0 + rgb(200,60,20) + [25% Blend] => rgb(127,179,185)
pSBC ( 0.75, color7, color3, true ); // rgb(200,60,20) + #67DAF0 + [75% Blend] => #7fb3b9

/*** Other Stuff ***/
// Error Checking
pSBC ( 0.42, "#FFBAA" ); // #FFBAA + [42% Lighter] => null  (Invalid Input Color)
pSBC ( 42, color1, color5 ); // rgb(20,60,200) + #F3A + [4200% Blend] => null  (Invalid Percentage Range)
pSBC ( 0.42, {} ); // [object Object] + [42% Lighter] => null  (Strings Only for Color)
pSBC ( "42", color1 ); // rgb(20,60,200) + ["42"] => null  (Numbers Only for Percentage)
pSBC ( 0.42, "salt" ); // salt + [42% Lighter] => null  (A Little Salt is No Good...)

// Error Check Fails (Some Errors are not Caught)
pSBC ( 0.42, "#salt" ); // #salt + [42% Lighter] => #a5a5a500  (...and a Pound of Salt is Jibberish)

// Ripping
pSBCr ( color4 ); // #5567DAF0 + [Rip] => [object Object] => {'r':85,'g':103,'b':218,'a':0.941}

下图将有助于显示两种混合方法的区别:


微函数

如果你真的想要速度和大小,你将不得不使用 RGB 而不是 HEX。 RGB 更直接、更简单,HEX 写入速度太慢,并且对于简单的两行代码(即,它可能是 3、4、6 或 8 位 HEX 代码)来说有太多的风格。您还需要牺牲一些功能,没有错误检查,没有 HEX2RGB 或 RGB2HEX。同样,您需要为颜色混合数学选择一个特定的函数(基于下面的函数名称),以及是否需要着色或混合。这些函数确实支持 Alpha 通道。当两种输入颜色都有 alpha 时,它将线性混合它们。如果这两种颜色中只有一种具有 alpha,它将直接传递给生成的颜色。以下是两个非常快速且小巧的线性函数:

const RGB_Linear_Blend=(p,c0,c1)=>{
    var i=parseInt,r=Math.round,P=1-p,[a,b,c,d]=c0.split(","),[e,f,g,h]=c1.split(","),x=d||h,j=x?","+(!d?h:!h?d:r((parseFloat(d)*P+parseFloat(h)*p)*1000)/1000+")"):")";
    return"rgb"+(x?"a(":"(")+r(i(a[3]=="a"?a.slice(5):a.slice(4))*P+i(e[3]=="a"?e.slice(5):e.slice(4))*p)+","+r(i(b)*P+i(f)*p)+","+r(i(c)*P+i(g)*p)+j;
}

const RGB_Linear_Shade=(p,c)=>{
    var i=parseInt,r=Math.round,[a,b,c,d]=c.split(","),P=p<0,t=P?0:255*p,P=P?1+p:1-p;
    return"rgb"+(d?"a(":"(")+r(i(a[3]=="a"?a.slice(5):a.slice(4))*P+t)+","+r(i(b)*P+t)+","+r(i(c)*P+t)+(d?","+d:")");
}

const RGB_Log_Blend=(p,c0,c1)=>{
    var i=parseInt,r=Math.round,P=1-p,[a,b,c,d]=c0.split(","),[e,f,g,h]=c1.split(","),x=d||h,j=x?","+(!d?h:!h?d:r((parseFloat(d)*P+parseFloat(h)*p)*1000)/1000+")"):")";
    return"rgb"+(x?"a(":"(")+r((P*i(a[3]=="a"?a.slice(5):a.slice(4))**2+p*i(e[3]=="a"?e.slice(5):e.slice(4))**2)**0.5)+","+r((P*i(b)**2+p*i(f)**2)**0.5)+","+r((P*i(c)**2+p*i(g)**2)**0.5)+j;
}

const RGB_Log_Shade=(p,c)=>{
    var i=parseInt,r=Math.round,[a,b,c,d]=c.split(","),P=p<0,t=P?0:p*255**2,P=P?1+p:1-p;
    return"rgb"+(d?"a(":"(")+r((P*i(a[3]=="a"?a.slice(5):a.slice(4))**2+t)**0.5)+","+r((P*i(b)**2+t)**0.5)+","+r((P*i(c)**2+t)**0.5)+(d?","+d:")");
}

想了解更多信息吗?阅读github 上的完整文章。

PT

(P.s.如果有人有其他混合方法的数学,请分享。)

【讨论】:

  • PHP 版本供需要的人使用:gist.github.com/chaoszcat/5325115#file-gistfile1-php
  • 我用过TinyColor -- tinycolor.darken(color,amount);
  • 很棒的帖子 ... :) ... 刚刚创建了它的 Swift 扩展:gist.github.com/matejukmar/1da47f7a950d1ba68a95
  • 这里是更新后的 shadeColor2 版本的 PHP 版本:function shadeColor2($color, $percent) { $color = str_replace("#", "", $color); $t=$percent&lt;0?0:255; $p=$percent&lt;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); }
  • 抱歉,我显然错过了这一点。可能有两个原因。第一个也是显而易见的,我使用 Math.Round 并且你不能使用十进制数字来进行准确的着色(颜色没有十六进制的小数)。例如,如果红色通道是8,则添加10% 会得到8.8,它会四舍五入为9。然后将9.09%9 分开,得到8.1819。哪个轮到8,所以这是一个不好的例子。但它仍然说明您正在使用9.09%9 而不是8.8。因此,其中可能有一些数字与我在这里的示例不完全相同。
【解决方案2】:

我提出了一个非常适合我的解决方案:

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

【讨论】:

  • 很好,我喜欢这个百分比! +1 寿,我可能会先做R = ((R&lt;255)?R:255).toString(16); 然后R = R.length==1 ? "0"+R : R 以提高速度。我不确定 toUpperCase 的意义何在?
  • 没必要。我只是在测试时添加它以进行漂亮的打印。我将对其进行编辑。
  • 非常好。但是,无论是什么颜色,100% 的浅色都不会变成全白,而 100% 的深色总是黑色吗?似乎 -100 确实会使任何颜色变黑,但 100(正)不会使其完全变白。
  • 不适用于#ff0000、#00ff00、#0000ff 等纯色
  • 为了让它与黑色一起工作,我刚刚做了这个 hack var R = parseInt(color.substring(1, 3), 16) var G = parseInt(color.substring(3, 5), 16) var B = parseInt(color.substring(5, 7), 16) if (R == 0) R = 32; if (G == 0) G = 32; if (B == 0) B = 32;
【解决方案3】:

这是一个基于 Eric 回答的超级简单的单线

function adjust(color, amount) {
    return '#' + color.replace(/^#/, '').replace(/../g, color => ('0'+Math.min(255, Math.max(0, parseInt(color, 16) + amount)).toString(16)).substr(-2));
}

例子:

adjust('#ffffff', -20) => "#ebebeb"
adjust('000000', 20) => "#141414"

【讨论】:

  • “超级简单”。
  • 金额是多少?可以帮助澄清它是否是 px、百分比等。
  • 您可以通过在该正则表达式中使用\w\w(与# 不匹配)来缩短它,而不是删除并重新添加#。我也不太明白你为什么要添加 0 然后删除它?这是我没有关注的一些 JS 东西吗(你已经在使用 toString(),所以你不需要强制转换它?)无论如何,我最终得到了以下内容,它的行为似乎相同:@ 987654329@
  • 为此添加了一个演示器...jsfiddle.net/Abeeee/xeos0p42/20
  • @MartinTournoij :'0'+substr(-2) 用于 0 到 15 之间的那些数字,它们在十六进制中只有一位,因此会给出格式错误的十六进制颜色字符串。他在前面加上“0”并保留最后两位数字,这样 9 就变成了“09”,而不仅仅是“9”。不过第一点很好! ?
【解决方案4】:

我在这里加上我的 2 美分,这是不同答案的令人满意的小组合:

const colorShade = (col, amt) => {
  col = col.replace(/^#/, '')
  if (col.length === 3) col = col[0] + col[0] + col[1] + col[1] + col[2] + col[2]

  let [r, g, b] = col.match(/.{2}/g);
  ([r, g, b] = [parseInt(r, 16) + amt, parseInt(g, 16) + amt, parseInt(b, 16) + amt])

  r = Math.max(Math.min(255, r), 0).toString(16)
  g = Math.max(Math.min(255, g), 0).toString(16)
  b = Math.max(Math.min(255, b), 0).toString(16)

  const rr = (r.length < 2 ? '0' : '') + r
  const gg = (g.length < 2 ? '0' : '') + g
  const bb = (b.length < 2 ? '0' : '') + b

  return `#${rr}${gg}${bb}`
}

接受或不以#开头的颜色,6个字符或3个字符。

使用示例:colorShade('#54b946', -40)

这是 4 种颜色的输出,每种颜色有 3 种浅色和 3 种深浅(这里的数量是 40 的倍数)。

【讨论】:

    【解决方案5】:

    这是我根据您的功能使用的。我更喜欢使用步数而不是百分比,因为它对我来说更直观。

    例如,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;
    
    }
    

    【讨论】:

    • 发现这比最佳答案有用得多,因为最佳答案使我的颜色非常强烈,而不仅仅是更暗。干杯埃里克
    • 迄今为止最好的答案,赞!
    【解决方案6】:

    我尝试了你的函数,但有一个小错误:例如,如果某个最终的 'r' 值仅为 1 位,则结果如下:例如,当正确的值为 '0a0a0a' 时,结果为:'a0a0a'。 我只是通过添加这个而不是你的回报来快速修复它:

    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;
    

    也许它不是很好,但它确实有效。很棒的功能,顺便说一句。正是我需要的。 :)

    【讨论】:

    • 感谢调试和赞美!太糟糕了,它不能回答是否有更快的方法,这是我的主要问题。就像可能使用所有十六进制且没有基本转换一样。寿,我猜你确实告诉我我是否有正确的代码(+1)。不幸的是,该修复增加了相当多的开销(现在您调用了 6 次 toString),并且 KISS 稍微减少了一些。在base16转换之前检查base10数字是否为15或更少可能会更快。但是,我喜欢!
    【解决方案7】:

    您是否考虑过 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

    编辑以上链接不再有效。您可以查看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;
    }
    

    假设:

    1. 您有函数hslToRgbrgbToHsl
    2. 参数colorValue#RRGGBB
    3. 形式的字符串

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

    【讨论】:

    • 很有趣,但是我不必从十六进制字符串转换为 rgb 到 hsl 吗?似乎它更复杂。也许我错过了一些东西。但是,我正在寻找一种 KISS 方式来做到这一点,并且尽可能快(执行时间)。我觉得理想情况下,如果我能用十六进制完成这一切,那将是最快的。但是,我在这里开发的解决方案涉及到 rgb 以便能够添加增量。
    • 是的,我认为它会更慢,更复杂,如果您不在其他任何地方使用 rgb 到 hsl 转换,那么它可能不是最简单的解决方案。然而,它会比添加 rgb 值更准确,尽管我自己并不是一个有色人种。这完全取决于我猜你想要的准确度。
    • 你提到的准确性损失是什么?我假设您的意思是所有 [web] 颜色都无法通过 rgb 或其他方式访问?
    • 正如我所说,我对颜色了解不多:wiki Color Theory
    • @Pimp Trizkit:它不太准确,因为(这只是我的理论......我不是色彩专家)你正在移动每个通道相同的数量,不管有多少开始的颜色。我认为这会导致饱和度降低,因为您使通道彼此靠近(按百分比)。当然,如果你上溢/下溢,那无论如何都是不可避免的。
    【解决方案8】:

    我想将颜色更改为 特定 亮度级别 - 无论颜色之前的亮度是多少 - 这是一个简单的 JS 函数,它似乎运行良好,尽管我确信它可能是更短

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

    【讨论】:

    • 酷!我假设p 的范围是0-100?我什至不知道如何正确定义 RGB 中的亮度,这是 HSL 的事情。例如,#FF00FF 是否比 #FF0000 亮?如果是这样,那就意味着洋红色的亮度是红色的两倍。因此,使用纯红色测试。传入纯红色#FF0000,设置为50%亮度,这里我们得到#FF4040,对吗?我猜想使红色亮度为 50%,我们会变得更暗,因为它已经完全亮了.. 如#800000 或 150% 亮度将是#FF8080。粉红色是不是更亮的红色?还是红色已经完全亮了?
    • 你是对的 - 我应该提到 p 必须在 1-100 的范围内!
    • #FF00FF 在红色通道中的值为 255,在绿色通道中为 0,在蓝色通道中为 255。通道中的组合值越高,颜色的亮度越高。数字 p 表示我们希望新颜色与原始颜色一样亮 50%。我不是 100% 认为#FF4040 是“50% 尽可能亮的红色”的正确答案。产生较深的阴影(在这种情况下,红色通道中的值较低)需要修改
    • 是的,我只是指出了在谈论 RGB 亮度时的歧义。如果转换为 HSL,L 通道实际上就是亮度。我的 [个人心理] 问题是,对我来说,#FF0000 是完全光明的。而#FF4040 更轻但不是更亮......对我来说,更轻意味着更接近白色,就像粉红色一样。亮度是它得到了多少,它得到了全红色,所以红色,是全亮的。因此,#FF0000 不能变得更亮……而是……更轻……也许我只是个怪胎,哈哈!我真的不知道颜色理论,所以,我真的只是在说我的...
    • 但我知道,当我改变显示器的亮度时,Reds 不会变成粉红色……对我来说。所以这可能是我开始逻辑的地方。
    【解决方案9】:

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

    【讨论】:

    • 以前从未使用过 C#,但看起来最后三个变量声明很奇怪。一个int 和两个vars 用于相同类型的数据。
    • C#中的var关键字表示让编译器在编译时推断类型。所以在上面的例子中 int 和 var 定义了一个相同类型的变量——int。如果您有一个长类型名称,或者如果您想引用匿名类型,这将很有用。这很奇怪,因为 user1618171 混合了两种变量声明样式 - 可能是错字。
    【解决方案10】:

    你的方法没问题 :) 我稍微简化了你的最短版本(用于饱和控制看here

    (col,amt)=> (+('0x'+col)+amt*0x010101).toString(16).padStart(6,0)
    

    // Similar to OP shortest version, we not have here # and colors range checking
    
    var LightenDarkenColor = 
         (col,amt) => (+('0x'+col)+amt*0x010101).toString(16).padStart(6,0);    
    
    
    
    
    // ------
    // TEST
    // ------
    
    function update() {
      let c= col.value.padEnd(6,'0').slice(0,6);
      let color = '#'+LightenDarkenColor(c, +amt.value);
      oldColor.innerHTML = 'Old: #'+c;
      oldColor.style = `background: #${c}`;
      newColor.innerHTML = 'New: '+color
      newColor.style = `background: ${color}`;
    
      
    }
    
    update();
    .box{ width: 100px; height: 100px; margin: 10px; display: inline-block}
    <input id="col" value="3F6D2A" oninput="update()">
    <input id="amt" value="30" oninput="update()"><br>
    <div id="oldColor" class="box"></div>
    <div id="newColor" class="box"></div>

    以及带有 # 和颜色范围检查的版本

    // # and colors range checking
    
    var LightenDarkenColor = 
         (col,amt) => '#'+col.slice(1).match(/../g)
                             .map(x=>(x=+`0x${x}`+amt,x<0?0:(x>255?255:x))
                             .toString(16).padStart(2,0)).join``;
    
    
    
    
    // ------
    // TEST
    // ------
    
    function update() {
      let c= col.value.padEnd(6,'0').slice(0,7);
      let color = LightenDarkenColor(c, +amt.value);
      oldColor.innerHTML = 'Old: '+c;
      oldColor.style = `background: ${c}`;
      newColor.innerHTML = 'New: '+color
      newColor.style = `background: ${color}`;
    }
    
    update();
    .box{ width: 100px; height: 100px; margin: 10px; display: inline-block}
    <input id="col" value="#3F6D2A" oninput="update()">
    <input id="amt" value="40" oninput="update()"><br>
    <div id="oldColor" class="box"></div>
    <div id="newColor" class="box"></div>

    【讨论】:

    • 我真的很喜欢这个简短而强大的功能的想法,但它似乎不适用于所有颜色。 :/ 例如:#54b946 apply -30, -60, -90, -120,它返回紫色而不是浅绿色。
    • @antoni 我更新了答案并对 sn-ps 进行了更多交互(但不更改主程序代码)。在底部 sn-p 中,我检查了您的颜色 - 似乎一切正常。如果没有 - 您能否提供十六进制数字与您期望的 #54b946 和 -120 的确切结果?
    • 那是我的错误@kamil,感谢您的功能。智能简洁。 +1 您的测试人员帮助我看到了代码中其他地方的错误。
    • 很好的答案,简单又实用!
    【解决方案11】:

    我只是使用了'#'前面的十六进制数字。

    var x = 0xf0f0f0;
    x=x+0xf00; //set this value as you wish programatically
    document.getElementById("heading").style = 'background-color: #'+x.toString(16);
    
    

    数字越大..颜色越浅

    【讨论】:

      【解决方案12】:

      我在 C# 中需要它,它可以帮助 .net 开发人员

      public static string LightenDarkenColor(string color, int amount)
          {
              int colorHex = int.Parse(color, System.Globalization.NumberStyles.HexNumber);
              string output = (((colorHex & 0x0000FF) + amount) | ((((colorHex >> 0x8) & 0x00FF) + amount) << 0x8) | (((colorHex >> 0xF) + amount) << 0xF)).ToString("x6");
              return output;
          }
      

      【讨论】:

      • 您转换了不处理前导零的“非工作”函数,并且总和可以超过 FF,= 修改上面的颜色分量...
      • 当我尝试该功能时,由于非十六进制值 (16 = 0xF) 和 (8 = 0x8),它不起作用,并在 8 个位置提供颜色,但现在效果很好跨度>
      • 你试过从FF增加吗? (例如从 0xFFFFFF + 0x000004):您的代码会翻转该最大值(例如到 0x1000003),而不是不增加,尤其是将 2 个上部颜色分量设置为 00,这是他们可以做的最大更改...
      • 你说得对,谢谢你的评论,除了限制 fff 和 000 的输入它会正常工作。
      【解决方案13】:

      我用打字稿写的版本:

      function changeColorLightness(color: number, lightness: number): number {
          return (Math.max(0, Math.min(((color & 0xFF0000) / 0x10000) + lightness, 0xFF)) * 0x10000) +
              (Math.max(0, Math.min(((color & 0x00FF00) / 0x100) + lightness, 0xFF)) * 0x100) +
              (Math.max(0, Math.min(((color & 0x0000FF)) + lightness, 0xFF)));
      }
      

      解释:

      export function changeColorLightness(color: number, lightness: number): number {
          const r = (color & 0xFF0000) / 0x10**4;
          const g = (color & 0x00FF00) / 0x10**2;
          const b = (color & 0x0000FF);
      
          const changedR = Math.max(0, Math.min(r + lightness, 0xFF));
          const changedG = Math.max(0, Math.min(g + lightness, 0xFF));
          const changedB = Math.max(0, Math.min(b + lightness, 0xFF));
      
          return (changedR * 0x10**4) + (changedG * 0x10**2) + changedB;
      }
      

      用法:

      changeColorLightness(0x00FF00, 0x50);
      changeColorLightness(parseInt("#00FF00".replace('#',''), 16), 0x50);
      changeColorLightness(0x00FF00, 127.5);
      

      【讨论】:

        【解决方案14】:

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

        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之间的double值(-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%;
        

        【讨论】:

          【解决方案15】:

          不支持从 00 开始的颜色,即“#000623”,但这里是修复

          function lightenDarkenColor(colorCode, amount) {
           let usePound = false;
          
           if (colorCode[0] == "#") {
               colorCode = colorCode.slice(1);
               usePound = true;
           }
           const num = parseInt(colorCode, 16);
           let r = (num >> 16) + amount;
          
           if (r > 255) {
               r = 255;
           } else if (r < 0) {
               r = 0;
           }
          
           let b = ((num >> 8) & 0x00FF) + amount;
          
           if (b > 255) {
               b = 255;
           } else if (b < 0) {
               b = 0;
           }
          
           let g = (num & 0x0000FF) + amount;
          
           if (g > 255) {
               g = 255;
           } else if (g < 0) {
               g = 0;
           }
           let color = (g | (b << 8) | (r << 16)).toString(16);
           while (color.length < 6){
             color = 0 + color;
           }
           return (usePound ? '#' : '') + color;  
          }
          

          【讨论】:

          【解决方案16】:

          基于 David Sherret 和 Pablo,上面的回答将解决方案转换为更安全的 Typescript 版本

          /**
           * @param color Hex value format: #ffffff or ffffff
           * @param decimal lighten or darken decimal value, example 0.5 to lighten by 50% or 1.5 to darken by 50%.
           */
          static shadeColor(color: string, decimal: number): string {
              const base = color.startsWith('#') ? 1 : 0;
          
              let r = parseInt(color.substring(base, 3), 16);
              let g = parseInt(color.substring(base + 2, 5), 16);
              let b = parseInt(color.substring(base + 4, 7), 16);
          
              r = Math.round(r / decimal);
              g = Math.round(g / decimal);
              b = Math.round(b / decimal);
          
              r = (r < 255)? r : 255;
              g = (g < 255)? g : 255;
              b = (b < 255)? b : 255;
          
              const rr = ((r.toString(16).length === 1)? `0${r.toString(16)}` : r.toString(16));
              const gg = ((g.toString(16).length === 1)? `0${g.toString(16)}` : g.toString(16));
              const bb = ((b.toString(16).length === 1)? `0${b.toString(16)}` : b.toString(16));
          
              return `#${rr}${gg}${bb}`;
          }
            
          

          【讨论】:

            【解决方案17】:

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

            【讨论】:

            • 这是 Pablo 答案的 php 版本。不幸的是,它比最终解决方案更长、更慢,并且不能准确地淡化颜色。它确实使它们变暗。用纯红色(#FF0000)测试,25%的亮度应该是(#FF4040)。查看我对 Kevin M 的最终解决方案 v2 的 PHP 版本的答案的结尾。
            【解决方案18】:

            我移植了优秀的 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

            【讨论】:

            • 我还没有分析代码,因为它与我的 OP(速度/大小/准确性)有关。但是在第一次阅读时,有一些 cmets 要做:1)我同意将十六进制转换为 RGB 可以看作是一个完全独立的函数。如果我的问题打算用干函数解决,这不是必需的。这里的目的是有一个答案(见我的第 2 版),它是超快速和超小(2 行!)和一个使十六进制颜色变亮和变暗的答案......特别是......作为一个独立的独立的功能。因此,在其最终用途中,它将是一个简单的单个函数调用。
            • 2) 而版本 3 的情况下,应大众需求,意图拥有一个完全独立的自包含通用功能,尽可能快且尽可能小,可以盲目地采取十六进制或 RGB 颜色及其所有变体。因此,需要将十六进制转换为 RGB。
            • 3) 对代码进行简单分析。看起来它运行速度要慢得多,而且显然比我的第 2 版大得多(这是对我的 OP 的真正答案;第 3 版适用于大众)。公平地说,我应该将此代码与我的 RGB 版本 2 进行比较,后者不进行转换,并且似乎回答了您关于干燥的观点。老实说,你的端口并不比我的 2 内六角更容易理解。所以,虽然它的干燥器,它实际上并没有那么简单,如果有的话。 (干燥对理解能力没有多大帮助)
            • 4) 如果您需要,我的 RGB 版本 2 是一个无转换 2 行功能。我对原始 OP 的特殊解决方案需要十六进制。这就是为什么有两种不同类型的第 2 版。但是您提到了关于干性和十六进制转换的观点,所以我们现在真正关注的是第 3 版。第 3 版来得晚得多。只有在第 2 版流行之后。
            • 5) 虽然我同意干燥通常有助于普遍性。在大多数情况下,为了理解能力。不幸的是,在这个例子中它是有代价的。这些成本是它更大,看起来更慢,并且似乎在堆栈(具有类似递归的性质)和全局(2 个函数;与 v2 相比)上使用更多内存。
            【解决方案19】:

            我一直希望能够产生色调/色调,这是我的 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);
                }
            };
            

            【讨论】:

            • 一些使用示例会有所帮助。也许还有一些解释为什么这个版本优于其他版本。这个版本似乎运行得相当慢。而且它更长。而且它似乎没有准确地遮蔽。看起来你在使用 LERP,或者类似的东西……这很好。不幸的是,它仅来自一个渠道,然后在所有渠道中使用相同的值。这是不对的,为了获得更高的准确度,你应该对每个通道单独进行 LERP。正如我对这个问题的回答一样。再加上它更小更快,检查错误并处理 rgb,并进行转换,我可以继续
            • 一个用法示例:varyHue("6e124c", 77) 其中第一个参数是十六进制颜色,第二个参数是百分比变化。正百分比改变阴影(变暗),而负值使结果变暗(变亮)。在我来到这个页面之前的几个小时,我写了这个例程作为我的第一次尝试,并且只是出于兴趣而发布它。我不知道我必须改进你的努力,或者在这样做之前我需要你的批准。完全是我自己的作品,不参考任何人。没听说过 LERP 我去看看,谢谢建议。
            • 呵呵,好吧,当然你什么都不用做!我们都感谢您的努力!我的第一个主要问题是首先列出的问题。试图帮助您回答问题,以便获得选票。 (显示用法和解释它的工作原理等) 其他的东西显然是一个快速分析,以帮助进一步每个人的知识。对不起,如果它看起来有点咄咄逼人。但另一个建议是让它接受十六进制颜色的#。对不起,如果它看起来像......“批准”......我将其视为同行评审。如果您不希望有人分析您的代码或提供反馈,我深表歉意。
            猜你喜欢
            • 2020-02-10
            • 1970-01-01
            • 2010-12-19
            • 2020-06-09
            • 2021-08-28
            • 2016-10-12
            • 1970-01-01
            相关资源
            最近更新 更多