Bene, questa risposta è diventata la sua bestia. Molte nuove versioni, stava diventando stupido a lungo. Mille grazie a tutti coloro che hanno contribuito a questa risposta. Ma, per renderlo semplice per le masse. Ho archiviato tutte le versioni / cronologia dell'evoluzione di questa risposta sul mio github . E ricominciato da capo su StackOverflow qui con la versione più recente. Un ringraziamento speciale va a Mike 'Pomax' Kamermans per questa versione. Mi ha dato la nuova matematica.
Questa funzione ( pSBC
) prenderà un colore web HEX o RGB.pSBC
può sfumare più scuro o più chiaro o mescolarlo con un secondo colore e può anche passarlo attraverso ma convertire da esadecimale a RGB (Hex2RGB) o da RGB a esadecimale (RGB2Hex). Tutto senza di te nemmeno sapere quale formato di colore stai usando.
Funziona molto velocemente, probabilmente il più veloce, soprattutto considerando le sue numerose funzionalità. È passato molto tempo. Vedi tutta la storia sul mio github . Se vuoi il modo assolutamente più piccolo e più veloce per sfumare o sfumare, vedi le Micro funzioni di seguito e usa uno dei demoni della velocità a 2 linee. Sono fantastici per animazioni intense, ma questa versione qui è abbastanza veloce per la maggior parte delle animazioni.
Questa funzione utilizza Log Blending o Linear Blending. Tuttavia, NON converte in HSL per schiarire o scurire correttamente un colore. Pertanto, i risultati di questa funzione differiranno da quelle funzioni molto più grandi e molto più lente che utilizzano HSL.
jsFiddle con pSBC
github> pSBC Wiki
Caratteristiche:
- Rileva automaticamente e accetta i colori esadecimali standard sotto forma di stringhe. Ad esempio:
"#AA6622"
o "#bb551144"
.
- Rileva automaticamente e accetta i colori RGB standard sotto forma di stringhe. Ad esempio:
"rgb(123,45,76)"
o"rgba(45,15,74,0.45)"
.
- Sfuma i colori in bianco o nero in percentuale.
- Unisce i colori insieme in percentuale.
- Esegue la conversione Hex2RGB e RGB2Hex contemporaneamente o da solo.
- Accetta codici colore HEX a 3 cifre (o 4 cifre con alpha), nel formato #RGB (o #RGBA). Li espanderà. Ad esempio:
"#C41"
diventa"#CC4411"
.
- Accetta e (lineare) fonde i canali alfa. Se il
c0
colore (da) o c1
(a) ha un canale alfa, il colore restituito avrà un canale alfa. Se entrambi i colori hanno un canale alfa, il colore restituito sarà una fusione lineare dei due canali alfa utilizzando la percentuale indicata (proprio come se fosse un canale di colore normale). Se solo uno dei due colori ha un canale alfa, questo alfa verrà semplicemente passato al colore restituito. Ciò consente di sfumare / sfumare un colore trasparente mantenendo il livello di trasparenza. Oppure, se anche i livelli di trasparenza dovessero fondersi, assicurati che entrambi i colori abbiano delle alfa. Durante l'ombreggiatura, passerà attraverso il canale alfa direttamente. Se vuoi l'ombreggiatura di base che ombreggia anche il canale alfa, usa rgb(0,0,0,1)
o rgb(255,255,255,1)
come tuoc1
(a) colore (o loro equivalenti esadecimali). Per i colori RGB, il canale alfa del colore restituito verrà arrotondato al terzo decimale.
- Le conversioni RGB2Hex e Hex2RGB sono implicite quando si utilizza la fusione. Indipendentemente dal
c0
(da) colore; il colore restituito sarà sempre nel formato colore del c1
(a) colore, se presente. Se non c'è nessun c1
(a) colore, passa 'c'
come c1
colore e sfumerà e convertirà qualunque sia il c0
colore. Se si desidera solo la conversione, passare anche 0
come percentuale ( p
). Se il c1
colore viene omesso o non string
viene passato, non verrà convertito.
- Una funzione secondaria viene aggiunta anche al globale.
pSBCr
può essere passato un colore esadecimale o RGB e restituisce un oggetto contenente queste informazioni sul colore. È nella forma: {r: XXX, g: XXX, b: XXX, a: X.XXX}. Where .r
, .g
e .b
hanno un intervallo compreso tra 0 e 255. E quando non è presente l'alfa: .a
è -1. Altrimenti: .a
ha un intervallo compreso tra 0.000 e 1.000.
- Per l'uscita RGB, emette
rgba()
sopra rgb()
quando un colore con un canale alfa è stato passato in c0
(da) e / o c1
(a).
- È stato aggiunto il controllo degli errori minori. Non è perfetto Può ancora bloccarsi o creare jibberish. Ma prenderà alcune cose. Fondamentalmente, se la struttura è in qualche modo sbagliata o se la percentuale non è un numero o non rientra nell'ambito, tornerà
null
. Un esempio:, pSBC(0.5,"salt") == null
dove come pensa #salt
sia un colore valido. Elimina le quattro righe che terminano return null;
per rimuovere questa funzione e renderla più veloce e più piccola.
- Utilizza la fusione dei log. Passare
true
per l
(il quarto parametro) per utilizzare la fusione lineare.
Codice:
// 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)
}
Uso:
// 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}
L'immagine seguente aiuterà a mostrare la differenza nei due metodi di fusione:
Micro funzioni
Se vuoi davvero velocità e dimensioni, dovrai usare RGB non HEX. RGB è più diretto e semplice, HEX scrive troppo lentamente ed è disponibile in troppi gusti per un semplice due righe (IE. Potrebbe essere un codice HEX a 3, 4, 6 o 8 cifre). Dovrai anche sacrificare alcune funzionalità, nessun controllo degli errori, nessun HEX2RGB né RGB2HEX. Inoltre, dovrai scegliere una funzione specifica (in base al nome della sua funzione di seguito) per la matematica di fusione dei colori e se vuoi ombreggiature o sfumature. Queste funzioni supportano i canali alfa. E quando entrambi i colori di input hanno gli alfa, li fonderà linearmente. Se solo uno dei due colori ha un alfa, lo passerà direttamente al colore risultante. Di seguito sono due funzioni di rivestimento che sono incredibilmente veloci e piccole:
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:")");
}
Vuoi maggiori informazioni? Leggi la recensione completa su github .
PT
(Ps Se qualcuno ha la matematica per un altro metodo di fusione, per favore condividi.)