Nun, diese Antwort ist zu einem eigenen Tier geworden. Viele neue Versionen, es wurde lange dumm. Vielen Dank an alle, die zu dieser Antwort beigetragen haben. Aber um es für die Massen einfach zu halten. Ich habe alle Versionen / den Verlauf der Entwicklung dieser Antwort in meinem Github archiviert . Und hier auf StackOverflow mit der neuesten Version von vorne angefangen. 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 es dunkler oder heller schattieren oder mit einer zweiten Farbe mischen und es auch direkt durchlaufen lassen, aber von Hex zu RGB (Hex2RGB) oder RGB zu Hex (RGB2Hex) konvertieren. Alles ohne dass Sie wissen, welches Farbformat Sie verwenden.
Dies läuft sehr schnell, wahrscheinlich am schnellsten, insbesondere angesichts der vielen Funktionen. Es war eine lange Zeit in der Herstellung. Sehen Sie die ganze Geschichte auf meinem Github . Wenn Sie den absolut kleinsten und schnellsten Weg zum Schattieren oder Mischen suchen, lesen Sie die unten stehenden Mikrofunktionen und verwenden Sie einen der 2-Liner-Geschwindigkeitsdämonen. Sie eignen sich hervorragend für intensive Animationen, aber diese Version hier ist für die meisten Animationen schnell genug.
Diese Funktion verwendet Log Blending oder Linear Blending. Es wird jedoch NICHT in HSL konvertiert, um eine Farbe richtig aufzuhellen oder abzudunkeln. Daher unterscheiden sich die Ergebnisse dieser Funktion von den viel größeren und viel langsameren Funktionen, die HSL verwenden.
jsFiddle mit pSBC
github> pSBC Wiki
Eigenschaften:
- Erkennt und akzeptiert Standard-Hex-Farben in Form von Zeichenfolgen automatisch. Zum Beispiel:
"#AA6622"
oder "#bb551144"
.
- Erkennt und akzeptiert Standard-RGB-Farben in Form von Zeichenfolgen automatisch. Zum Beispiel:
"rgb(123,45,76)"
oder "rgba(45,15,74,0.45)"
.
- Schattiert die Farben prozentual in Weiß oder Schwarz.
- Mischt Farben prozentual zusammen.
- Konvertiert Hex2RGB und RGB2Hex gleichzeitig oder solo.
- Akzeptiert 3-stellige (oder 4-stellige mit Alpha) HEX-Farbcodes in der Form #RGB (oder #RGBA). Es wird sie erweitern. Zum Beispiel:
"#C41"
wird "#CC4411"
.
- Akzeptiert und mischt Alphakanäle (linear). Wenn entweder die
c0
(von) Farbe oder die c1
(bis) Farbe einen Alpha-Kanal hat, hat die zurückgegebene Farbe einen Alpha-Kanal. Wenn beide Farben einen Alphakanal haben, ist die zurückgegebene Farbe eine lineare Mischung der beiden Alphakanäle unter Verwendung des angegebenen Prozentsatzes (als wäre es ein normaler Farbkanal). Wenn nur eine der beiden Farben einen Alphakanal hat, wird dieses Alpha nur an die zurückgegebene Farbe weitergeleitet. Dies ermöglicht das Mischen / Schattieren einer transparenten Farbe unter Beibehaltung des Transparenzniveaus. Wenn die Transparenzstufen ebenfalls gemischt werden sollen, stellen Sie sicher, dass beide Farben Alphas enthalten. Beim Schattieren wird der Alphakanal gerade durchlaufen. Wenn Sie eine grundlegende Schattierung wünschen, die auch den Alphakanal schattiert, verwenden Sie rgb(0,0,0,1)
oder rgb(255,255,255,1)
als Ihrec1
(zu) Farbe (oder deren 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 hat immer das Farbformat der c1
(zu) Farbe, falls vorhanden. Wenn es keine c1
(zu) Farbe gibt, geben Sie sie 'c'
als c1
Farbe ein und sie schattiert und konvertiert die c0
Farbe. Wenn nur eine Konvertierung gewünscht wird, geben Sie diese auch 0
als Prozentsatz ( p
) ein. Wenn die c1
Farbe weggelassen oder ein Nicht übergeben string
wird, wird sie nicht konvertiert.
- Eine sekundäre Funktion wird ebenfalls zur globalen hinzugefügt.
pSBCr
kann eine Hex- oder RGB-Farbe übergeben werden und es wird ein Objekt zurückgegeben, das diese Farbinformationen enthält. Es hat die Form: {r: XXX, g: XXX, b: XXX, a: X.XXX}. Wo .r
, .g
und .b
hat Bereich von 0 bis 255. Und wenn es keine Alpha ist: .a
-1. Ansonsten: .a
hat einen Bereich von 0,000 bis 1.000.
- Für RGB - Ausgang, gibt er
rgba()
über , rgb()
wenn eine Farbe mit einem Alphakanal zu übergeben wurde c0
(von) und / oder c1
(to).
- Kleinere Fehlerprüfung wurde hinzugefügt. Es ist nicht perfekt. Es kann immer noch abstürzen oder Quatsch verursachen. Aber es wird ein paar Sachen fangen. Grundsätzlich wird zurückgegeben, wenn die Struktur in irgendeiner Weise falsch ist oder wenn der Prozentsatz keine Zahl ist oder außerhalb des Gültigkeitsbereichs liegt
null
. Ein Beispiel: pSBC(0.5,"salt") == null
Wo, wie es denkt, #salt
eine gültige Farbe ist. Löschen Sie die vier Zeilen, die mit enden return null;
, um diese Funktion zu entfernen und sie schneller und kleiner zu machen.
- Verwendet Log Blending. Übergeben Sie
true
für l
(den 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)
}
Verwendungszweck:
// 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}
Das folgende Bild zeigt 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 ist in zu vielen Varianten für einen einfachen Zweiliner erhältlich (dh es kann sich um einen 3-, 4-, 6- oder 8-stelligen HEX-Code handeln). Sie müssen auch einige Funktionen opfern, keine Fehlerprüfung, kein HEX2RGB oder RGB2HEX. Außerdem müssen Sie eine bestimmte Funktion (basierend auf dem Funktionsnamen unten) für die Farbüberblendungsmathematik auswählen und wenn Sie Schattierungen oder Überblendungen wünschen. Diese Funktionen unterstützen Alphakanäle. Und wenn beide Eingabefarben Alphas haben, werden sie linear gemischt. Wenn nur eine der beiden Farben ein Alpha hat, wird es direkt an die resultierende Farbe weitergegeben. Im Folgenden sind zwei Liner-Funktionen aufgeführt, 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:")");
}
Willst du mehr Infos? Lesen Sie den vollständigen Artikel über Github .
PT
(Ps Wenn jemand die Mathematik für eine andere Mischmethode hat, teile sie bitte mit.)