글쎄,이 대답은 그 자신의 짐승이되었습니다. 많은 새로운 버전, 어리석은 짓이 길어졌습니다. 이 답변에 많은 기여를 해주신 모든 분들께 감사드립니다. 그러나 대중을 위해 단순하게 유지하기 위해. 이 답변의 진화에 대한 모든 버전 / 역사를 내 github에 보관했습니다 . 그리고 최신 버전으로 여기에서 StackOverflow를 깨끗하게 시작했습니다. 이 버전에 대해 Mike 'Pomax'Kamermans 에게 특별한 감사를드립니다 . 그는 나에게 새로운 수학을 주었다.
이 기능 ( pSBC
)은 16 진수 또는 RGB 웹 색상을 사용합니다. pSBC
어둡거나 밝게 음영 처리하거나 두 번째 색상과 혼합하고 오른쪽을 통해 전달할 수도 있지만 16 진수에서 RGB (Hex2RGB) 또는 RGB에서 16 진수 (RGB2Hex)로 변환 할 수도 있습니다. 어떤 색상 형식을 사용하고 있는지조차 모릅니다.
특히 많은 기능을 고려할 때 가장 빠르며 아마도 가장 빠릅니다. 제작에 오랜 시간이 걸렸습니다. 내 github 의 전체 이야기를 참조하십시오 . 가장 작고 빠른 음영 처리 또는 혼합 방법을 원하면 아래의 마이크로 기능을 참조하여 2 라이너 속도 악마 중 하나를 사용하십시오. 강렬한 애니메이션에는 훌륭하지만이 버전은 대부분의 애니메이션에 충분히 빠릅니다.
이 기능은 로그 블렌딩 또는 선형 블렌딩을 사용합니다. 그러나 색상을 올바르게 밝게하거나 어둡게하기 위해 HSL로 변환되지 않습니다. 따라서이 기능의 결과는 HSL을 사용하는 훨씬 크고 느린 기능과 다릅니다 .
pSBC가 포함 된 jsFiddle
github> pSBC 위키
풍모:
- 문자열 형태의 표준 16 진수 색상을 자동 감지하고 받아들입니다. 예를 들면 다음
"#AA6622"
과 같습니다. 또는 "#bb551144"
.
- 문자열 형태의 표준 RGB 색상을 자동 감지하고 수용합니다. 예를 들면 다음
"rgb(123,45,76)"
과 같습니다. 또는 "rgba(45,15,74,0.45)"
.
- 백분율로 색상을 흰색 또는 검은 색으로 음영 처리합니다.
- 백분율로 색상을 혼합합니다.
- Hex2RGB와 RGB2Hex 변환을 동시에 수행하거나 단독으로 수행합니다.
- #RGB (또는 #RGBA) 형식으로 3 자리 (또는 4 자리 (알파 포함) HEX) 색상 코드를 사용할 수 있습니다. 그것들을 확장시킬 것입니다. 예를 들면 다음과 같습니다
"#C41"
된다 "#CC4411"
.
- 알파 채널을 수락하고 (선형) 혼합합니다. 중 하나 경우
c0
(에서) 색상 또는 c1
(을) 색상은 알파 채널을 가지고, 다음 반환 된 색상은 알파 채널을해야합니다. 두 색상에 모두 알파 채널이있는 경우 반환 된 색상은 주어진 비율 (일반 색상 채널 인 것처럼)을 사용하여 두 알파 채널의 선형 혼합입니다. 두 색상 중 하나에 만 알파 채널이있는 경우이 알파는 반환 된 색상으로 전달됩니다. 이를 통해 투명도 수준을 유지하면서 투명 색상을 혼합 / 음영 할 수 있습니다. 또는 투명도 수준도 혼합해야하는 경우 두 색상에 모두 알파가 있는지 확인하십시오. 음영 처리시 알파 채널을 통해 직선으로 전달됩니다. 당신은 또한 알파 채널을 음영 기본 음영을 원한다면, 사용 rgb(0,0,0,1)
또는 rgb(255,255,255,1)
같은c1
(to) 색상 (또는 해당하는 16 진수). RGB 색상의 경우 반환 된 색상의 알파 채널은 소수점 이하 3 자리로 반올림됩니다.
- 블렌딩을 사용할 때 RGB2Hex 및 Hex2RGB 변환은 암시 적입니다.
c0
(from) 색상에 관계없이 ; 반환 된 색상은 항상 c1
(to) 색상 의 색상 형식입니다 (있는 경우). 어떤이없는 경우 c1
(에) 색상, 다음 통과 'c'
는 AS의 c1
색상과 그늘과 어떤 변환됩니다 c0
색상입니다. 변환 만 필요한 경우 0
백분율 ( p
) 로도 전달 하십시오 . 경우 c1
색상이 생략 또는 비가 string
전달되고,이 변환하지 않습니다.
- 보조 기능도 전역에 추가됩니다.
pSBCr
16 진수 또는 RGB 색상을 전달할 수 있으며이 색상 정보가 포함 된 객체를 반환합니다. {r : XXX, g : XXX, b : XXX, a : X.XXX} 형식입니다. 여기서 .r
, .g
및 .b
범위는 0 ~ 255입니다. 알파가없는 경우 : .a
-1입니다. 그렇지 않은 경우 : .a
범위는 0.000 ~ 1.000입니다.
- RGB 출력의 경우 알파 채널이있는 색상이 (시작) 및 / 또는 (
rgba()
끝) rgb()
으로 전달되면 출력 됩니다 .c0
c1
- 사소한 오류 검사가 추가되었습니다. 완벽하지 않습니다. 여전히 충돌하거나 혼란 스러울 수 있습니다. 그러나 그것은 약간의 물건을 잡을 것입니다. 기본적으로 구조가 어떤 방식으로 잘못되었거나 백분율이 숫자가 아니거나 범위를 벗어나면을 반환
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}
아래 그림은 두 가지 혼합 방법의 차이점을 보여줍니다.
마이크로 기능
속도와 크기를 정말로 원한다면 16 진수가 아닌 RGB를 사용해야합니다. RGB는 더 간단하고 간단합니다. HEX는 쓰기 속도가 너무 느리고 간단한 두 줄짜리 (IE, 3, 4, 6 또는 8 자리 HEX 코드 일 수 있음)에 비해 너무 많은 맛이 있습니다. 또한 일부 기능, 오류 검사, HEX2RGB 또는 RGB2HEX를 희생해야합니다. 또한 색상 혼합 수학 및 음영 또는 혼합을 원하는 경우 특정 기능 (아래의 기능 이름을 기준으로)을 선택해야합니다. 이 기능은 알파 채널을 지원합니다. 두 입력 색상에 모두 알파가 있으면 선형 혼합됩니다. 두 색상 중 하나에 만 알파가있는 경우 결과 색상으로 그대로 전달됩니다. 다음은 매우 빠르고 작은 두 가지 라이너 기능입니다.
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
(Ps 다른 블렌딩 방법에 대한 수학이 있다면 공유하십시오.)