Nun, diese Antwort hat sich zu einer eigenen Angelegenheit entwickelt. Viele neue Versionen, es wurde einfach zu lang. Vielen Dank an all die vielen, vielen Mitwirkenden an dieser Antwort. Aber, um es für die Masse einfach zu halten. Ich habe alle Versionen/Geschichte der Entwicklung dieser Antwort auf meiner Website archiviert github . Und habe es hier auf StackOverflow mit der neuesten Version neu gestartet. Ein besonderer Dank geht an Mike 'Pomax' Kamermans für diese Version. Er gab mir die neue Mathematik.
Diese Funktion ( pSBC
) nimmt eine HEX- oder RGB-Webfarbe an. pSBC
kann sie dunkler oder heller schattieren oder mit einer zweiten Farbe mischen und kann sie auch direkt durchlaufen, aber von Hex nach RGB (Hex2RGB) oder RGB nach Hex (RGB2Hex) konvertieren. Und das alles, ohne dass Sie überhaupt wissen, welches Farbformat Sie verwenden.
Es läuft wirklich schnell, wahrscheinlich am schnellsten, vor allem wenn man die vielen Funktionen bedenkt. Es war eine lange Zeit in der Entwicklung. Siehe die ganze Geschichte auf meiner github . Wenn Sie die absolut kleinstmögliche und schnellste Art des Schattierens oder Verblendens wünschen, sehen Sie sich die Mikrofunktionen unten an und verwenden Sie einen der 2-Liner Speed Demons. Sie sind großartig für intensive Animationen, aber diese Version hier ist schnell genug für die meisten Animationen.
Diese Funktion verwendet Log Blending oder Linear Blending. Sie wandelt jedoch NICHT in HSL um, um eine Farbe richtig aufzuhellen oder abzudunkeln. Deshalb, Die Ergebnisse dieser Funktion werden sich unterscheiden von den viel größeren und viel langsameren Funktionen, die HSL verwenden.
jsFiddle mit pSBC
github > pSBC-Wiki
Merkmale:
- Automatische Erkennung und Annahme von Standard-Hex-Farben in Form von Zeichenketten. Zum Beispiel:
"#AA6622"
o "#bb551144"
.
- Automatische Erkennung und Annahme von Standard-RGB-Farben in Form von Zeichenketten. Zum Beispiel:
"rgb(123,45,76)"
o "rgba(45,15,74,0.45)"
.
- Schattiert Farben prozentual zu Weiß oder Schwarz.
- Mischt Farben prozentual zusammen.
- Konvertiert Hex2RGB und RGB2Hex gleichzeitig oder alleine.
- Akzeptiert 3-stellige (oder 4-stellige mit Alpha) HEX-Farbcodes in der Form #RGB (oder #RGBA). Es wird sie expandieren. Zum Beispiel:
"#C41"
wird "#CC4411"
.
- Akzeptiert und überblendet (linear) Alphakanäle. Wenn entweder die
c0
(von) Farbe oder die c1
(bis) Farbe einen Alphakanal hat, dann hat die zurückgegebene Farbe einen Alphakanal. Wenn beide Farben einen Alphakanal haben, wird die zurückgegebene Farbe eine lineare Mischung der beiden Alphakanäle mit dem angegebenen Prozentsatz sein (so als ob es ein normaler Farbkanal wäre). Wenn nur eine der beiden Farben einen Alphakanal hat, wird dieser Alphakanal einfach an die zurückgegebene Farbe durchgereicht. Auf diese Weise kann eine transparente Farbe überblendet/abgeschattet werden, während die Transparenzstufe beibehalten wird. Oder, wenn die Transparenzstufen ebenfalls überblendet werden sollen, stellen Sie sicher, dass beide Farben Alphakanäle haben. Beim Schattieren wird der Alphakanal direkt durchgereicht. Wenn Sie eine einfache Schattierung wünschen, die auch den Alphakanal schattiert, dann verwenden Sie rgb(0,0,0,1)
o rgb(255,255,255,1)
als Ihr c1
(bis) Farbe (oder ihre Hex-Äquivalente). Bei RGB-Farben wird der Alphakanal der zurückgegebenen Farbe auf 3 Dezimalstellen gerundet.
- RGB2Hex- und Hex2RGB-Konvertierungen sind bei der Verwendung von Blending implizit. Unabhängig von der
c0
(von) Farbe; die zurückgegebene Farbe entspricht immer dem Farbformat der c1
(zu) Farbe, wenn es eine gibt. Wenn es keine gibt c1
(zu) Farbe, dann passieren 'c'
in als die c1
Farbe und schattiert und konvertiert, was immer die c0
Farbe ist. Wenn nur eine Konvertierung gewünscht ist, dann übergeben Sie 0
als Prozentsatz eingeben ( p
) sowie. Wenn die c1
Farbe weggelassen wird oder eine nicht string
übergeben wird, wird es nicht konvertiert.
- Außerdem wird dem Global eine sekundäre Funktion hinzugefügt.
pSBCr
kann eine Hex- oder RGB-Farbe übergeben werden und gibt ein Objekt zurück, das diese Farbinformationen enthält. Es hat die Form: {r: XXX, g: XXX, b: XXX, a: X.XXX}. Wobei .r
, .g
y .b
haben einen Bereich von 0 bis 255. Und wenn es kein Alpha gibt: .a
ist -1. Andernfalls: .a
hat einen Bereich von 0,000 bis 1,000.
- Für die RGB-Ausgabe gibt er Folgendes aus
rgba()
sur rgb()
wenn eine Farbe mit einem Alphakanal in c0
(von) und/oder c1
(zu).
- Eine kleine Fehlerprüfung wurde hinzugefügt. Sie ist nicht perfekt. Sie kann immer noch abstürzen oder Kauderwelsch erzeugen. Aber sie fängt einige Dinge ab. Wenn die Struktur in irgendeiner Weise falsch ist oder wenn der Prozentsatz keine Zahl ist oder außerhalb des Gültigkeitsbereichs liegt, wird grundsätzlich Folgendes zurückgegeben
null
. Ein Beispiel: pSBC(0.5,"salt") == null
während sie denkt #salt
ist eine gültige Farbe. Löschen Sie die vier Zeilen, die mit return null;
um diese Funktion zu entfernen und sie schneller und kleiner zu machen.
- Verwendet Log Blending. Durchlauf
true
für l
(der 4. Parameter), um die lineare Überblendung zu verwenden.
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.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)
}
Verwendung:
// 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}
Die nachstehende Abbildung verdeutlicht den Unterschied zwischen den beiden Mischmethoden:
Mikrofunktionen
Wenn Sie wirklich Geschwindigkeit und Größe wollen, müssen Sie RGB und nicht HEX verwenden. RGB ist unkomplizierter und einfacher, HEX schreibt zu langsam und hat zu viele Varianten für einen einfachen Zweizeiler (z. B. könnte es ein 3-, 4-, 6- oder 8-stelliger HEX-Code sein). Außerdem müssen Sie auf einige Funktionen verzichten: keine Fehlerprüfung, kein HEX2RGB oder RGB2HEX. Außerdem müssen Sie eine bestimmte Funktion (basierend auf dem unten stehenden Funktionsnamen) für die Berechnung der Farbmischung wählen und angeben, ob Sie eine Schattierung oder eine Überblendung wünschen. Diese Funktionen unterstützen Alphakanäle. Wenn beide Eingabefarben Alphakanäle haben, werden sie linear gemischt. Wenn nur eine der beiden Farben einen Alphakanal hat, wird dieser direkt an die resultierende Farbe weitergegeben. Im Folgenden finden Sie zwei Linienfunktionen, die unglaublich schnell und klein sind:
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:")");
}
Möchten Sie mehr Informationen? Lesen Sie den vollständigen Bericht auf github .
PT
(P.s. Wenn jemand die Mathematik für eine andere Mischmethode kennt, bitte mitteilen).