Konvertering fargerom i JavaScript

0
8

En utfordring jeg møtte i å bygge et image “emojifier” var at jeg trengte å endre fargen områder av verdier som er innhentet ved hjelp av getImageData() fra RGB til HSL. Jeg brukte matriser av emojis arrangert av lysstyrke og fargemetning, og de var HSL-basert for det beste kamper av gjennomsnittlig pixel farger med emojis.

I denne artikkelen vil vi studere funksjoner som vil være nyttig for å konvertere både uklar og alfa-aktivert farge verdier. Moderne nettlesere i dag støtter RGB-fargerom(A), hex, og HSL(EN). Funksjoner og notasjoner for disse er (rgb), rgba(), #rgb/#rrggbb, #rgba/#rrggbbaa, hsl(), og hsla(). Nettlesere har alltid støttet bygget-i navn som aliceblue som godt.

Langs veien, vil vi støte på bruk av noen farge syntaxes gitt av et nytt Nivå 4 av CSS Farger Modul. For eksempel, nå har vi hex med alpha som vi har nevnt (#rgba/#rrggbbaa) og RGB og HSL syntaxes ikke lenger krever komma (verdier som rgb(255 0 0) og hsl(240 100% 50%) ble lovlig!).

Nettleser støtte for CSS Farger Nivå 4 er ikke universelle når dette skrives, så ikke forvent ny farge syntaxes å jobbe i Microsoft nettlesere eller Safari hvis du prøver dem i CSS.

RGB til Hex

Konvertere RGB til hex er rett og slett bare en endring av radices. Vi konvertere den røde, grønne og blå verdier fra desimal til heksadesimale ved hjelp av toString(16). Etter prepending 0s å enkelt tegn og under, kan vi sette sammen dem og # til en enkelt tilbake uttalelsen.

funksjonen RGBToHex(r,g,b) {
r = r.toString(16);
g = g.toString(16);
b = b.toString(16);

hvis (r.lengde == 1)
r = “0” + r;
hvis (g.lengde == 1)
g = “0” + g;
hvis (b.lengde == 1)
b = “0” + b;

return “#” + r + g + b;
}
RGB i Streng

Alternativt kan vi bruke en enkelt streng argumentet med rød, grønn og blå, atskilt med komma eller mellomrom (f.eks. “rgb(255,25,2)”, “rgb(255 25 2)”). Delstreng å eliminere rgb (split hva som er igjen av den ), så splittet som følge første elementet av hvilket skilletegn (sep). r, g og b skal bli lokale variabler nå. Da vi bruke + før splitte strenger å konvertere dem tilbake til tall før å få den heksadesimale verdier.

funksjonen RGBToHex(rgb) {
// Velger riktig skilletegn
la sep = rgb.indexOf(“,”) > -1 ? “,” : “”;
// Turn “rgb(r,g,b)” inn [r,g,b]
rgb = rgb.substr(4).split(“)”)[0].split(sep);

la r = (+rgb[0]).toString(16),
g = (+rgb[1]).toString(16),
b = (+rgb[2]).toString(16);

hvis (r.lengde == 1)
r = “0” + r;
hvis (g.lengde == 1)
g = “0” + g;
hvis (b.lengde == 1)
b = “0” + b;

return “#” + r + g + b;
}

I tillegg kan vi tillate strenger med kanal verdier som prosentandeler ved å legge til løkken etter å redefinere rgb. Det vil stripe %s og turn hva som er igjen til verdier ut av 255.

funksjonen RGBToHex(rgb) {
la sep = rgb.indexOf(“,”) > -1 ? “,” : “”;
rgb = rgb.substr(4).split(“)”)[0].split(sep);

// Konvertere %s for å 0-255
for (la R i rgb) {
la r = rgb[R];
hvis (r.indexOf(“%”) > -1)
rgb[R] = Matematikk.runde(r.substr(0,r.lengde – 1) / 100 * 255);
/* Eksempel:
75% -> 191
75/100 = 0.75, * 255 = 191.25 -> 191
*/
}


}

Nå kan vi levere verdier som en av disse:

  • rgb(255,25,2)
  • rgb(255 25 2)
  • rgb(50%,30%,10%)
  • rgb(50% 30% 10%)

RGBA til Hex (#rrggbbaa)

Konvertering RGBA til hex med #rgba eller #rrggbbaa notasjon følger praktisk talt den samme prosessen som ugjennomsiktig motstykke. Siden alfa (a) er normalt en verdi mellom 0 og 1, må vi multiplisere det med 255, runde resultatet, deretter konvertere den til heksadesimal.

funksjonen RGBAToHexA(r,g,b,a) {
r = r.toString(16);
g = g.toString(16);
b = b.toString(16);
a = Matematikk.runde(a * 255).toString(16);

hvis (r.lengde == 1)
r = “0” + r;
hvis (g.lengde == 1)
g = “0” + g;
hvis (b.lengde == 1)
b = “0” + b;
hvis (a.lengde == 1)
a = “0” + a;

return “#” + r + g + b + a;
}

For å gjøre dette med en streng (inkludert med prosenter), kan vi følge med på hva vi gjorde tidligere. Vær også oppmerksom på at ekstra trinn for skjøting ut en skråstrek. Siden CSS Farger Nivå 4 støtter syntax av rgba(r g b / a), dette er hvor vi tillater det. Alpha verdier kan nå være prosenter! Dette fjerner 0-1-bare sjakler vi pleide å ha. Derfor, for-løkke sykkeltur gjennom rgba skal omfatte en del å tørke % fra alpha uten å multiplisere med 255 (når R er 3 for alfa). Snart kan vi bruke verdier som rgba(255 128 0 / 0.8) og rgba(100% 21% 100% / 30%)!

funksjonen RGBAToHexA(rgba) {
la sep = rgba.indexOf(“,”) > -1 ? “,” : “”;
rgba = rgba.substr(5).split(“)”)[0].split(sep);

// Stripe skråstrek hvis du bruker plass-skilt syntaks
hvis (rgba.indexOf(“/”) > -1)
rgba.skjøte(3,1);

for (la R i rgba) {
la r = rgba[R];
hvis (r.indexOf(“%”) > -1) {
la p = r.substr(0,r.lengde – 1) / 100;

hvis (R < 3) {
rgba[R] = Matematikk.runde(p * 255);
} else {
rgba[R] = p;
}
}
}
}

Så, der tv er konvertert til hex, og vi justerer en for å bruke et element av rgba[].

funksjonen RGBAToHexA(rgba) {

la r = (+rgba[0]).toString(16),
g = (+rgba[1]).toString(16),
b = (+rgba[2]).toString(16),
a = Matematikk.runde(+rgba[3] * 255).toString(16);

hvis (r.lengde == 1)
r = “0” + r;
hvis (g.lengde == 1)
g = “0” + g;
hvis (b.lengde == 1)
b = “0” + b;
hvis (a.lengde == 1)
a = “0” + a;

return “#” + r + g + b + a;
}

Nå funksjonen støtter følgende:

  • rgba(255,25,2,0.5)
  • rgba(255 25 2 / 0.5)
  • rgba(50%,30%,10%,0.5)
  • rgba(50%,30%,10%,50%)
  • rgba(50% 30% 10% / 0.5)
  • rgba(50% 30% 10% / 50%)

Hex til RGB

Vi vet at lengden av heksadesimale verdier, må være enten 3 eller 6 (pluss #). I begge tilfeller, vi begynner hver rød (r), grønn (g) og blå (b) verdien med “0x” til å konvertere dem til hex. Hvis vi gir en 3-sifret verdi, og vi vil sette sammen den samme verdi to ganger for hver kanal. Hvis det er en 6-sifret verdi, kan vi sette sammen de første to røde, to neste for grønt, og de to siste for blå. For å få verdiene for den endelige rgb() string, vi sette _root. variablene som er med på + for å konvertere dem fra strenger tilbake til tall, som vil gi desimaler vi trenger.

funksjonen hexToRGB(h) {
la r = 0, g = 0, b = 0;

// 3 sifre
hvis (h.lengde == 4) {
r = “0x” + h[1] + h[1];
g = “0x” + h[2] + h[2];
b = “0x” + h[3] + t[3];

// 6 siffer
} else if (h.lengde == 7) {
r = “0x” + h[1] + h[2];
g = “0x” + h[3] + t[4];
b = “0x” + h[5] + h[6];
}

return “rgb(“+ +r + “,” + +g + “,” + +b + “)”;
}
RGB-utgang med %s

Hvis vi ønsker å gå tilbake (rgb) ved hjelp av prosenter, så vi kan endre funksjonen for å bruke en valgfri isPct parameter som dette:

funksjonen hexToRGB(h,isPct) {
la r = 0, g = 0, b = 0;
isPct = isPct === true;

hvis (h.lengde == 4) {
r = “0x” + h[1] + h[1];
g = “0x” + h[2] + h[2];
b = “0x” + h[3] + t[3];

} else if (h.lengde == 7) {
r = “0x” + h[1] + h[2];
g = “0x” + h[3] + t[4];
b = “0x” + h[5] + h[6];
}

hvis (isPct) {
r = +(r / 255 * 100).toFixed(1);
g = +(g / 255 * 100).toFixed(1);
b = +(b / 255 * 100).toFixed(1);
}

return “rgb(” + (isPct ? r + “%,” + g + “%,” + b + “%” : +r + “,” + +g + “,” + +b) + “)”;
}

Under den siste if-setning, ved hjelp av +s vil konvertere r, g, og b til tall. Hver toFixed(1) sammen med dem vil runde resultatet til nærmeste tiende. I tillegg, vi vil ikke ha hele tall med .0 eller tiår gamle innfall som produserer tall som 0.30000000000000004. Derfor, i retur, vi utelatt +s rett før den første r, g og b for å hindre NaNs forårsaket av %s. Nå kan vi bruke hexToRGB(“#ff0”,true) for å få rgb(100%,100%,0%)!

Hex (#rrggbbaa) til RGBA

Prosedyren for heksadesimale verdier med alpha bør igjen være lik med den siste. Vi bare gjenkjenne en 4 – eller 8-sifret verdi (pluss #) deretter konvertere alfa og dele det med 255. For å få mer nøyaktig utgang, men ikke lenge desimal tall for alfa, kan vi bruke toFixed(3).

funksjonen hexAToRGBA(h) {
la r = 0, g = 0, b = 0, a = 1;

hvis (h.lengde == 5) {
r = “0x” + h[1] + h[1];
g = “0x” + h[2] + h[2];
b = “0x” + h[3] + t[3];
a = “0x” + h[4] + t[4];

} else if (h.lengde == 9) {
r = “0x” + h[1] + h[2];
g = “0x” + h[3] + t[4];
b = “0x” + h[5] + h[6];
a = “0x” + h[7] + h[8];
}
a = +(a / 255).toFixed(3);

return “rgba(” + +r + “,” + +g + “,” + +b + “,” + a + “)”;
}
Utgang RGBA med %s

For en versjon som utganger prosenter, vi kan gjøre hva vi gjorde i hexToRGB()—bryteren for r, g og b for å 0-100% når isPct er sant.

funksjonen hexAToRGBA(h,isPct) {
la r = 0, g = 0, b = 0, a = 1;
isPct = isPct === true;

// Håndtering av sifre

hvis (isPct) {
r = +(r / 255 * 100).toFixed(1);
g = +(g / 255 * 100).toFixed(1);
b = +(b / 255 * 100).toFixed(1);
}
a = +(a / 255).toFixed(3);

return “rgba(” + (isPct ? r + “%,” + g + “%,” + b + “%,” + a : +r + “,” + +g + “,” + +b + “,” + a) + “)”;
}

Her er en rask løsning hvis alfa burde være en prosentandel, for: flytte uttalelse der a er omdefinert over den siste if-setning. Så i denne uttalelsen, endre en til å være som for r, g og b. Når isPct er sant, må også få %.

funksjonen hexAToRGBA(h,isPct) {

a = +(a / 255).toFixed(3);
hvis (isPct) {
r = +(r / 255 * 100).toFixed(1);
g = +(g / 255 * 100).toFixed(1);
b = +(b / 255 * 100).toFixed(1);
a = +(a * 100).toFixed(1);
}

return “rgba(” + (isPct ? r + “%,” + g + “%,” + b + “%,” + a + “%” : +r + “,” + +g + “,” + +b + “,” + a) + “)”;
}

Når vi går inn #7f7fff80 nå, bør vi få rgba(127,127,255,0.502) eller rgba(49.8%,49.8%,100%,50.2%).

RGB til HSL

Å skaffe HSL-verdier fra RGB-eller hex er en litt mer krevende fordi det er en større formel som er involvert. For det første, vi må dele den røde, grønne og blå med 255 til å bruke verdier mellom 0 og 1. Så finner vi den laveste og høyeste av disse verdiene (cmin og cmax) samt forskjellen mellom dem (delta). Vi trenger at resultatet som en del av beregningen kulør og metning. Rett etter delta, la oss initialisere fargetone (h), metning (s), og letthet (l).

funksjonen RGBToHSL(r,g,b) {
// Gjør for r, g og b fraksjoner av 1
r /= 255;
g /= 255;
b /= 255;

// Finn største og minste kanal verdier
la cmin = Matematikk.min(r,g,b),
cmax = Matematikk.max(r,g,b),
delta = cmax – cmin,
h = 0,
s = 0,
l = 0;
}

Neste, vi trenger for å beregne nyanse, som er å være bestemt av den største kanalen verdi i cmax (eller hvis alle kanalene er den samme). Hvis det er ingen forskjell mellom kanalene, nyanse vil være 0. Hvis cmax er rød, så formelen vil være ((g – b) / delta) % 6. Hvis grønt, så (b – r) / delta + 2. Så, hvis blå, (r – g) / delta + 4. Til slutt, må du multiplisere resultatet med 60 (for å få graden verdi) og runde det. Siden nyanser bør ikke være negativ, vil vi legge til 360 til det, hvis det er nødvendig.

funksjonen RGBToHSL(r,g,b) {

// Beregne hue
// Ingen forskjell
hvis (delta == 0)
h = 0;
// Rød er maks
else if (cmax == r)
h = ((g – b) / delta) % 6;
// Grønne er maks
else if (cmax == g)
h = (b – r) / delta + 2;
// Blått er maks
annet
h = (r – g) / delta + 4;

h = Matematikk.runde(h * 60);

// Gjør negative fargetoner positiv bak 360°
if (h < 0)
h += 360;
}

Alt som er igjen er den metning og lyshet. La oss beregne letthet før vi gjør metning, som metning vil avhenge av det. Det er summen av maksimum og minimum kanal verdier halvert ((cmax + cmin) / 2). Deretter delta vil avgjøre hva metning vil være. Hvis det er 0 (ingen forskjell mellom cmax og cmin), metning (saturation) er automatisk 0. Ellers, vil det være 1 minus den absolutte verdien av to ganger letthet minus 1 (1 – Matematikk.abs(2 * l – 1)). Når vi har disse verdiene, må vi konvertere dem til verdier ut over 100%, så vi multiplisere dem med 100 og runde av til nærmeste tiende. Nå kan vi sette sammen vår hsl().

funksjonen RGBToHSL(r,g,b) {

// Beregne letthet
l = (cmax + cmin) / 2;

// Beregne metning
s = delta == 0 ? 0 : delta / (1 – Matematikk.abs(2 * l – 1));

// Formere l og s ved 100
s = +(s * 100).toFixed(1);
l = +(l * 100).toFixed(1);

return “hsl(” + h + “,” + r + “%,” + l + “%)”;
}
RGB i Streng

For en streng, dele argumentet med komma eller mellomrom, stripe %s, og lokalisere r, g og b som vi gjorde før.

funksjonen RGBToHSL(rgb) {
la sep = rgb.indexOf(“,”) > -1 ? “,” : “”;
rgb = rgb.substr(4).split(“)”)[0].split(sep);

for (la R i rgb) {
la r = rgb[R];
hvis (r.indexOf(“%”) > -1)
rgb[R] = Matematikk.runde(r.substr(0,r.lengde – 1) / 100 * 255);
}

// Gjør for r, g og b fraksjoner av 1
la r = rgb[0] / 255,
g = rgb[1] / 255,
b = rgb[2] / 255;


}

RGBA å HSLA

I forhold til hva vi gjorde bare for å konvertere RGB til HSL, alfa kollega vil være utgangspunktet ingenting! Vi bare gjenbruke koden for RGB til HSL (multi-argument-versjon), kan du la en alene, og passerer en til returnert HSLA. Husk at det bør være mellom 0 og 1.

funksjonen RGBAToHSLA(r,g,b,a) {
// Kode for RGBToHSL(r,g,b) før retur

return “hsla(” + h + “,” + r + “%,” +l + “%,” + a + “)”;
}
RGBA i Streng

For string-verdier, bruker vi splitting og stripping logikk igjen, men bruk det fjerde elementet i rgba for en. Husk den nye rgba(r g b / a) syntaks? Vi ansette aksept av det som vi gjorde for RGBAToHexA(). Så resten av koden er vanlig RGB-til-HSL-konvertering.

funksjonen RGBAToHSLA(rgba) {
la sep = rgba.indexOf(“,”) > -1 ? “,” : “”;
rgba = rgba.substr(5).split(“)”)[0].split(sep);

// Stripe skråstrek hvis du bruker plass-skilt syntaks
hvis (rgba.indexOf(“/”) > -1)
rgba.skjøte(3,1);

for (la R i rgba) {
la r = rgba[R];
hvis (r.indexOf(“%”) > -1) {
la p = r.substr(0,r.lengde – 1) / 100;

hvis (R < 3) {
rgba[R] = Matematikk.runde(p * 255);
} else {
rgba[R] = p;
}
}
}

// Gjør for r, g og b fraksjoner av 1
la r = rgba[0] / 255,
g = rgba[1] / 255,
b = rgba[2] / 255,
a = rgba[3];

// Resten av RGB-til-HSL logikk

}

Ønsker å la alfa-som er? Fjern annet uttalelse fra for-løkke.

for (la R i rgba) {
la r = rgba[R];
hvis (r.indexOf(“%”) > -1) {
la p = r.substr(0,r.lengde – 1) / 100;

hvis (R < 3) {
rgba[R] = Matematikk.runde(p * 255);
}
}
}

HSL til RGB

Det tar litt mindre logikk for å konvertere HSL tilbake til RGB enn motsatt vei. Siden vi skal bruke en rekke 0-100 for metning og lyshet, er det første trinnet er å dele dem med 100 til verdier mellom 0 og 1. Neste, vi finner chroma (c), som er farge intensitet, slik at (1 – Matematikk.abs(2 * l – 1)) * s. Deretter bruker vi x for den nest største komponenten (første blir chroma), beløp å legge til hver kanal for å matche letthet (m), og initialisere r, g, b.

funksjonen HSLToRGB(h,s,l) {
// Må være brøkdeler av 1
s /= 100;
l /= 100;

la c = (1 – Matematikk.abs(2 * l – 1)) * s,
x = c * (1 – Matematikk.abs((h / 60) % 2 – 1)),
m = l – p/2,
r = 0,
g = 0,
b = 0;
}

Kulør vil avgjøre hva den røde, grønne og blå bør være avhengig av hvilken 60° sektor av fargehjulet det ligger.

Fargehjulet delt inn i 60° segmenter

Deretter c og x skal være angitt som vist nedenfor, forlater en kanal på 0. For å få det endelige RGB-verdi, vi legge til m til hver kanal, må du multiplisere den med 255, og rundt den.

funksjonen HSLToRGB(h,s,l) {

if (0 <= h && h < 60) {
r = c; g = x; b = 0;
} else if (60 <= h && h < 120) {
r = x; g = c; b = 0;
} else if (120 <= h && h < 180) {
r = 0; g = c; b = x;
} else if (180 <= h && h < 240) {
r = 0; g = x; b = c;
} else if (240 <= h && h < 300) {
r = x; g = 0; b = c;
} else if (300 <= h && h < 360) {
r = c; g = 0; b = x;
}
r = Matematikk.round((r + m) * 255);
g = Matematikk.round((g + m) * 255);
b = Matematikk.round((b + m) * 255);

return “rgb(” + r + “,” + g + “,” + b + “)”;
}
HSL i Streng

For enkelt streng versjon, vi endre de første par uttalelser i utgangspunktet på samme måte som vi gjorde for RGBToHSL(r,g,b). Fjern s /= 100; og l /= 100, og vi vil bruke den nye uttalelser til tørk de 4 første tegnene og ) for vårt utvalg av HSL-verdier, så den %s fra s og l før du deler dem med 100.

funksjonen HSLToRGB(hsl) {
la sep = hsl.indexOf(“,”) > -1 ? “,” : “”;
hsl = hsl.substr(4).split(“)”)[0].split(sep);

la h = hsl[0],
s = hsl[1].substr(0,hsl[1].lengde – 1) / 100,
l = hsl[2].substr(0,hsl[2].lengde – 1) / 100;


}

Neste håndfull av uttalelser skal håndtere fargetoner utstyrt med en enhet—grader, radianer eller svinger. Vi multiplisere radianer ved 180/π og slår av 360. Hvis resultatet ender opp med over 360, vi sammensatte modulus dele for å holde det innenfor rammen. Alt dette vil skje før vi har avtale med c, x og m.

funksjonen HSLToRGB(hsl) {

// Stripe etikett og konvertere til grader (hvis nødvendig)
hvis (h.indexOf(“deg”) > -1)
h = h.substr(0,h.lengde – 3);
else if (h.indexOf(“hjul”) > -1)
h = Matematikk.runde(h.substr(0,h.lengde – 3) * (180 / Matematikk.PI));
else if (h.indexOf(“turn”) > -1)
h = Matematikk.runde(h.substr(0,h.lengde – 4) * 360);
// Holde hue brøkdel av 360 hvis du slutter opp over
hvis (h >= 360)
h %= 360;

// Konvertering til RGB begynner

}

Etter gjennomføring trinnene ovenfor, nå følgende trygt kan brukes:

  • hsl(180 100% 50%)
  • hsl(180deg,100%,50%)
  • hsl(180deg 100% 50%)
  • hsl(3.14 rad,100%,50%)
  • hsl(3.14 rad 100% 50%)
  • hsl(0.5 slå,100%,50%)
  • hsl(0.5 slå 100% 50%)

Puh, det er ganske fleksibilitet!

RGB-utgang med %s

På samme måte, vi kan endre denne funksjonen til å returnere prosent verdier akkurat som vi gjorde i hexToRGB().

funksjonen HSLToRGB(hsl,isPct) {
la sep = hsl.indexOf(“,”) > -1 ? “,” : “”;
hsl = hsl.substr(4).split(“)”)[0].split(sep);
isPct = isPct === true;

hvis (isPct) {
r = +(r / 255 * 100).toFixed(1);
g = +(g / 255 * 100).toFixed(1);
b = +(b / 255 * 100).toFixed(1);
}

return “rgb(“+ (isPct ? r + “%,” + g + “%,” + b + “%” : +r + “,” + +g + “,” + +b) + “)”;
}

HSLA til RGBA

Igjen, håndtering alphas vil være en no-brainer. Vi kan bruke på nytt-kode for den opprinnelige HSLToRGB(h,s,l) og legge til en retur.

funksjonen HSLAToRGBA(h,s,l,a) {
// Kode for HSLToRGB(h,s,l) før retur

return “rgba(” + r + “,” + g + “,” + b + “,” + a + “)”;
}
HSLA i Streng

Endre den til ett argument, hvordan vi vil håndtere strenger her vil ikke være for mye annerledes enn det vi gjorde tidligere. En ny HSLA-syntaks Farger fra Nivå 4 bruker (verdi verdi verdi / value) akkurat som RGBA, så ha kode for å håndtere det, vil vi være i stand til å plugge i noe som hsla(210 100% 50% / 0.5) her.

funksjonen HSLAToRGBA(hsla) {
la sep = hsla.indexOf(“,”) > -1 ? “,” : “”;
hsla = hsla.substr(5).split(“)”)[0].split(sep);

hvis (hsla.indexOf(“/”) > -1)
hsla.skjøte(3,1);

la h = hsla[0],
s = hsla[1].substr(0,hsla[1].lengde – 1) / 100,
l = hsla[2].substr(0,hsla[2].lengde – 1) / 100,
a = hsla[3];

hvis (h.indexOf(“deg”) > -1)
h = h.substr(0,h.lengde – 3);
else if (h.indexOf(“hjul”) > -1)
h = Matematikk.runde(h.substr(0,h.lengde – 3) * (180 / Matematikk.PI));
else if (h.indexOf(“turn”) > -1)
h = Matematikk.runde(h.substr(0,h.lengde – 4) * 360);
hvis (h >= 360)
h %= 360;


}

Videre, disse andre kombinasjoner har blitt mulig:

  • hsla(180,100%,50%,50%)
  • hsla(180 100% 50% / 50%)
  • hsla(180deg,100%,50%,0.5)
  • hsla(3.14 rad,100%,50%,0.5)
  • hsla(0.5 slå 100% 50% / 50%)

RGBA med %s

Da kan vi gjenskape den samme logikk for å gi ut prosenter, inkludert alpha. Hvis alfa bør være en prosentandel (søkte i pctFound), her er hvordan vi kan håndtere det:

  1. Hvis r, g og b er å bli konvertert til prosenter, så en bør være multiplisert med 100, hvis det ikke allerede er en prosentandel. Ellers, slippe %, og det vil bli lagt tilbake i retur.
  2. Hvis r, g, og b bør være alene, så fjerner % fra en og del a av 100.

funksjonen HSLAToRGBA(hsla,isPct) {
// Koden opp til å kutte stripping

isPct = isPct === true;

// h, s, l, definert til å avrunding av r, g, b

la pctFound = en.indexOf(“%”) > -1;

hvis (isPct) {
r = +(r / 255 * 100).toFixed(1);
g = +(g / 255 * 100).toFixed(1);
b = +(b / 255 * 100).toFixed(1);
if (!pctFound) {
a *= 100;
} else {
a = a.substr(0,.lengde – 1);
}

} else if (pctFound) {
a = a.substr(0,.lengde – 1) / 100;
}

return “rgba(“+ (isPct ? r + “%,” + g + “%,” + b + “%,” + a + “%” : +r + “,”+ +g + “,” + +b + “,” + +a) + “)”;
}

Hex til HSL

Du kanskje tror at dette ene og den neste er galere prosesser enn de andre, men de bare kommer i to deler med resirkulert logikk. Først, vi konverterer det heksadesimale til RGB. Det gir oss basen 10s vi trenger å konvertere til HSL.

funksjonen hexToHSL(H) {
// Konvertere hex til RGB første
la r = 0, g = 0, b = 0;
hvis (H. lengde == 4) {
r = “0x” + H[1] + H[1];
g = “0x” + H[2] + H[2];
b = “0x” + H[3] + T[3];
} else if (H. lengde == 7) {
r = “0x” + H[1] + H[2];
g = “0x” + H[3] + T[4];
b = “0x” + H[5] + H[6];
}
// Så å HSL
r /= 255;
g /= 255;
b /= 255;
la cmin = Matematikk.min(r,g,b),
cmax = Matematikk.max(r,g,b),
delta = cmax – cmin,
h = 0,
s = 0,
l = 0;

hvis (delta == 0)
h = 0;
else if (cmax == r)
h = ((g – b) / delta) % 6;
else if (cmax == g)
h = (b – r) / delta + 2;
annet
h = (r – g) / delta + 4;

h = Matematikk.runde(h * 60);

if (h < 0)
h += 360;

l = (cmax + cmin) / 2;
s = delta == 0 ? 0 : delta / (1 – Matematikk.abs(2 * l – 1));
s = +(s * 100).toFixed(1);
l = +(l * 100).toFixed(1);

return “hsl(” + h + “,” + r + “%,” + l + “%)”;
}

Hex (#rrggbbaa) til HSLA

Det er ikke så mange linjer som endring i dette. Vi vil gjenta det som vi nylig gjorde for å få alpha ved å konvertere hex, men det vil ikke dele det med 255 gang. Først må vi få nyanse, metning og lyshet som vi gjorde i den andre til-HSL-funksjoner. Så, før den slutter tilbake, vi deler alfa og angi antall desimaler.

funksjonen hexAToHSLA(H) {
la r = 0, g = 0, b = 0, a = 1;

hvis (H. lengde == 5) {
r = “0x” + H[1] + H[1];
g = “0x” + H[2] + H[2];
b = “0x” + H[3] + T[3];
a = “0x” + H[4] + T[4];
} else if (H. lengde == 9) {
r = “0x” + H[1] + H[2];
g = “0x” + H[3] + T[4];
b = “0x” + H[5] + H[6];
a = “0x” + H[7] + H[8];
}

// Normal konvertering til HSL

a = (a / 255).toFixed(3);

return “hsla(“+ h + “,” + r + “%,” + l + “%,” + a + “)”;
}

HSL til Hex

Dette starter som en konvertering til RGB, men det er et ekstra trinn for å Regnestykket.round()s konvertere RGB-resultater til hex.

funksjonen HSLToHex(h,s,l) {
s /= 100;
l /= 100;

la c = (1 – Matematikk.abs(2 * l – 1)) * s,
x = c * (1 – Matematikk.abs((h / 60) % 2 – 1)),
m = l – p/2,
r = 0,
g = 0,
b = 0;

if (0 <= h && h < 60) {
r = c; g = x; b = 0;
} else if (60 <= h && h < 120) {
r = x; g = c; b = 0;
} else if (120 <= h && h < 180) {
r = 0; g = c; b = x;
} else if (180 <= h && h < 240) {
r = 0; g = x; b = c;
} else if (240 <= h && h < 300) {
r = x; g = 0; b = c;
} else if (300 <= h && h < 360) {
r = c; g = 0; b = x;
}
// Har oppnådd RGB, konvertere tv til hex
r = Matematikk.round((r + m) * 255).toString(16);
g = Matematikk.round((g + m) * 255).toString(16);
b = Matematikk.round((b + m) * 255).toString(16);

// Sette _root. 0s hvis det er nødvendig
hvis (r.lengde == 1)
r = “0” + r;
hvis (g.lengde == 1)
g = “0” + g;
hvis (b.lengde == 1)
b = “0” + b;

return “#” + r + g + b;
}
HSL i Streng

Selv de første linjene av denne funksjonen vil være som de i HSLToRGB() hvis vi endret det til å godta en enkelt streng. Dette er hvordan vi har vært å skaffe nyanse, metning og lyshet separat i første omgang. La oss ikke glemme det skritt å fjerne hue etikett og konvertere til grader, også. Alt dette vil være på plass for s /= 100; og l /= 100;.

funksjonen HSLToHex(hsl) {
la sep = hsl.indexOf(“,”) > -1 ? “,” : “”;
hsl = hsl.substr(4).split(“)”)[0].split(sep);

la h = hsl[0],
s = hsl[1].substr(0,hsl[1].lengde – 1) / 100,
l = hsl[2].substr(0,hsl[2].lengde – 1) / 100;

// Stripe etikett og konvertere til grader (hvis nødvendig)
hvis (h.indexOf(“deg”) > -1)
h = h.substr(0,h.lengde – 3);
else if (h.indexOf(“hjul”) > -1)
h = Matematikk.runde(h.substr(0,h.lengde – 3) * (180 / Matematikk.PI));
else if (h.indexOf(“turn”) > -1)
h = Matematikk.runde(h.substr(0,h.lengde – 4) * 360);
hvis (h >= 360)
h %= 360;


}

HSLA til Hex (#rrggbbaa)

Legge til alfa til mix, kan vi konvertere til hex og legge til en fjerde om å sette _root. en 0, hvis det er nødvendig. Du har sannsynligvis allerede kjent med denne logikken fordi vi brukte det sist i RGBAToHexA().

funksjonen HSLAToHexA(h,s,l,a) {
// Gjenta koden fra HSLToHex(h,s,l) til 3 `toString(16)`s

a = Matematikk.runde(a * 255).toString(16);

hvis (r.lengde == 1)
r = “0” + r;
hvis (g.lengde == 1)
g = “0” + g;
hvis (b.lengde == 1)
b = “0” + b;
hvis (a.lengde == 1)
a = “0” + a;

return “#” + r + g + b + a;
}
HSLA i Streng

Til slutt, linjer i enkelt argument versjon opp til en = hsla[3] er ikke annerledes enn de av HSLAToRGBA().

funksjonen HSLAToHexA(hsla) {
la sep = hsla.indexOf(“,”) > -1 ? “,” : “”;
hsla = hsla.substr(5).split(“)”)[0].split(sep);

// Stripe skråstrek
hvis (hsla.indexOf(“/”) > -1)
hsla.skjøte(3,1);

la h = hsla[0],
s = hsla[1].substr(0,hsla[1].lengde – 1) / 100,
l = hsla[2].substr(0,hsla[2].lengde – 1) / 100,
a = hsla[3];


}

Innebygd Navn

For å konvertere en navngitt farge til RGB, hex, eller HSL, kan du vurdere å slå dette bordet med 140+ navn og heksadesimale verdier inn i et massivt objekt ved start. Sannheten er at vi egentlig ikke trenger en, fordi her er hva vi kan gjøre:

  1. Opprette et element
  2. Gi det en tekst farge
  3. Få verdien av at eiendommen
  4. Fjerne elementet
  5. Tilbake lagret farge verdi, som vil være i RGB-standard

Så, vår funksjon å få RGB vil bare være sju uttalelser!

funksjonen nameToRGB(navn)) {
// Oppretter falske div
la fakeDiv = – dokument.createElement(“div”);
fakeDiv.stil.color = navn;
dokumentet.kroppen.appendChild(fakeDiv);

// Få farge av div
la cs = vinduet.getComputedStyle(fakeDiv),
pv = cs.getPropertyValue(“farger”);

// Fjern div etter å få ønsket farge verdi
dokumentet.kroppen.removeChild(fakeDiv);

tilbake pv,
}

La oss gå enda lenger. Hvordan om vi endre utgang til hex-i stedet?

funksjonen nameToHex(navn)) {
// Få RGB fra navngitte farge i midlertidige div
la fakeDiv = – dokument.createElement(“div”);
fakeDiv.stil.color = navn;
dokumentet.kroppen.appendChild(fakeDiv);

la cs = vinduet.getComputedStyle(fakeDiv),
pv = cs.getPropertyValue(“farger”);

dokumentet.kroppen.removeChild(fakeDiv);

// Kode som er hentet fra RGBToHex() (unntatt pv er substringed)
la rgb = pv.substr(4).split(“)”)[0].split(“,”),
r = (+rgb[0]).toString(16),
g = (+rgb[1]).toString(16),
b = (+rgb[2]).toString(16);

hvis (r.lengde == 1)
r = “0” + r;
hvis (g.lengde == 1)
g = “0” + g;
hvis (b.lengde == 1)
b = “0” + b;

return “#” + r + g + b;
}

Eller, hvorfor ikke HSL? 😉

funksjonen nameToHSL(navn)) {
la fakeDiv = – dokument.createElement(“div”);
fakeDiv.stil.color = navn;
dokumentet.kroppen.appendChild(fakeDiv);

la cs = vinduet.getComputedStyle(fakeDiv),
pv = cs.getPropertyValue(“farger”);

dokumentet.kroppen.removeChild(fakeDiv);

// Kode som er hentet fra RGBToHSL() (unntatt pv er substringed)
la rgb = pv.substr(4).split(“)”)[0].split(“,”),
r = rgb[0] / 255,
g = rgb[1] / 255,
b = rgb[2] / 255,
cmin = Matematikk.min(r,g,b),
cmax = Matematikk.max(r,g,b),
delta = cmax – cmin,
h = 0,
s = 0,
l = 0;

hvis (delta == 0)
h = 0;
else if (cmax == r)
h = ((g – b) / delta) % 6;
else if (cmax == g)
h = (b – r) / delta + 2;
annet
h = (r – g) / delta + 4;

h = Matematikk.runde(h * 60);

if (h < 0)
h += 360;

l = (cmax + cmin) / 2;
s = delta == 0 ? 0 : delta / (1 – Matematikk.abs(2 * l – 1));
s = +(s * 100).toFixed(1);
l = +(l * 100).toFixed(1);

return “hsl(” + h + “,” + r + “%,” + l + “%)”;
}

I det lange løp, hver konvertering fra et navn blir en konvertering fra RGB etter sprengning navnet.

Validering Av Farger

I alle disse funksjonene, har det ikke vært noen tiltak for å hindre eller rette latterlig inngang (si fargetoner over 360 eller prosenter over 100). Hvis vi bare manipulere punkter på en <lerret> hentet ved hjelp av getImageData(), validering av farge verdier er ikke nødvendig før du konverterer, fordi de vil være riktig uansett hva. Hvis vi skal lage en farge konvertering verktøy der brukerne levere farge, så validering ville være mye som trengs.

Det er enkelt å håndtere feil inngang for tv som separate argumenter, som dette for RGB:

// Korrigere røde
hvis (r > 255)
r = 255;
else if (r < 0)
r = 0;

Hvis validering av en hel streng, så et vanlig uttrykk er nødvendig. For eksempel, dette er RGBToHex () – funksjonen gitt en validering for trinn med et uttrykk:

funksjonen RGBToHex(rgb) {
// Uttrykk for (rgb) syntaxes
la ex = /^rgb((((((((1?[1-9]?d)|10d|(2[0-4]d)|25[0-5]),s?)){2}|((((1?[1-9]?d)|10d|(2[0-4]d)|25[0-5])s)){2})((1?[1-9]?d)|10d|(2[0-4]d)|25[0-5]))|((((([1-9]?d(.d+)?)|100|(.d+))%,s?){2}|((([1-9]?d(.d+)?)|100|(.d+))%s){2})(([1-9]?d(.d+)?)|100|(.d+))%)))$/i;

hvis (ex.test(rgb)) {
// Logikk for å konvertere RGB til hex

} else {
// Noe å gjøre hvis fargen er ugyldig
}
}

For å teste andre typer verdier, nedenfor er en tabell over uttrykk for å dekke både uklar og alfa-aktivert:

Fargen Verdi
RegEx
RGB /^rgb((((((((1?[1-9]?d)|10d|(2[0-4]d)|25[0-5]),s?)){2}|((((1?[1-9]?d)|10d|(2[0-4]d)|25[0-5])s)){2})((1?[1-9]?d)|10d|(2[0-4]d)|25[0-5]))|((((([1-9]?d(.d+)?)|100|(.d+))%,s?){2}|((([1-9]?d(.d+)?)|100|(.d+))%s){2})(([1-9]?d(.d+)?)|100|(.d+))%)))$/i
RGBA /^rgba((((((((1?[1-9]?d)|10d|(2[0-4]d)|25[0-5]),s?)){3})|(((([1-9]?d(.d+)?)|100|(.d+))%,s?){3}))|(((((1?[1-9]?d)|10d|(2[0-4]d)|25[0-5])s){3})|(((([1-9]?d(.d+)?)|100|(.d+))%s){3}))/s)((0?.d+)|[01]|(([1-9]?d(.d+)?)|100|(.d+))%))$/i
Hex /^#([da-f]{3}){1,2}$/jeg
Hex (med Alpha) /^#([da-f]{4}){1,2}$/jeg
HSL /^hsl(((((([12]?[1-9]?d)|[12]0d|(3[0-5]d))(.d+)?)|(.d+))(deg)?|(0/0?.d+)turn|(([0-6](.d+)?)|(.d+))rad)((,s?(([1-9]?d(.d+)?)|100|(.d+))%){2}|(s(([1-9]?d(.d+)?)|100|(.d+))%){2}))$/i
HSLA /^hsla(((((([12]?[1-9]?d)|[12]0d|(3[0-5]d))(.d+)?)|(.d+))(deg)?|(0/0?.d+)turn|(([0-6](.d+)?)|(.d+))rad)(((,s?(([1-9]?d(.d+)?)|100|(.d+))%){2},s?)|((s(([1-9]?d(.d+)?)|100|(.d+))%){2}s/s))((0?.d+)|[01]|(([1-9]?d(.d+)?)|100|(.d+))%))$/i

Se på uttrykk for RGB(A) og HSL(A), har du sannsynligvis har store øyne akkurat nå, disse ble gjort omfattende nok til å omfatte de fleste av de nye syntaxes fra CSS Farger Nivå 4. Hex, på den annen side, trenger ikke uttrykk så lenge de andre på grunn av bare sifferet teller. I et øyeblikk, vil vi i dybden på disse og dechiffrere deler. Vær oppmerksom på at bokstaver verdier (/i) å gi alle disse.

RGB
/^rgb((((((((1?[1-9]?d)|10d|(2[0-4]d)|25[0-5]),s?)){2}|((((1?[1-9]?d)|10d|(2[0-4]d)|25[0-5])s)){2})((1?[1-9]?d)|10d|(2[0-4]d)|25[0-5]))|((((([1-9]?d(.d+)?)|100|(.d+))%,s?){2}|((([1-9]?d(.d+)?)|100|(.d+))%s){2})(([1-9]?d(.d+)?)|100|(.d+))%)))$/i

Fordi rgb() aksepterer enten alle heltall eller alle prosenter, begge tilfeller er dekket. I ytterste gruppe, mellom ^rgb( og )$, det er indre grupper for både heltall og prosenter, alt komma-områder eller områder som bare separatorer:

  1. (((((1?[1-9]?d)|10d|(2[0-4]d)|25[0-5]),s?){2}|(((1?[1-9]?d)|10d|(2[0-4]d)|25[0-5])s){2})((1?[1-9]?d)|10d|(2[0-4]d)|25[0-5]))
  2. ((((([1-9]?d(.d+)?)|100|(.d+))%,s?){2}|((([1-9]?d(.d+)?)|100|(.d+))%s){2})(([1-9]?d(.d+)?)|100|(.d+))%)

I første halvdel, aksepterer vi to tilfeller av heltall for rødt og grønt fra 0-99 eller 111-199 ((1?[1-9]?d)), 100-109 (10d), 200-249 ((2[0-4]d)), eller 250-255 (25[0-5]). Vi kunne ikke bare gjøre d{1,3} fordi verdier som 03 eller 017 og de som er større enn 255 bør ikke være tillatt. Etter det går komma og valgfri plass (, s?). På den andre siden av | etter den første {2} (som angir to forekomster av heltall), vil vi se etter det samme med mellomrom som skilletegn hvis venstre side er falske. Så for blå, det samme burde være akseptert, men uten skilletegn.

I den andre halvparten, akseptable verdier for prosenter, inkludert flyter, bør enten være 0-99, eksplisitt 100 og ikke en dupp, eller flyter under 1 med 0 droppet. Derfor segmentet her er (([1-9]?d(.d+)?)|100|(.d+)), og det vises tre ganger, to ganger med skilletegn (, s?){2}, % s){2}), en gang uten.

Det er lovlig å bruke prosenter uten mellomrom som skilletegn (rgb(100%50%10%), for eksempel) i CSS, men de funksjonene vi skrev ikke støtter det. Det samme gjelder for rgba(100%50%10%/50%), hsl(40 100%50%), og hsla(40 100%50%/0.5). Dette kan meget vel være et pluss for kode golf og minification!

RGBA
/^rgba((((((((1?[1-9]?d)|10d|(2[0-4]d)|25[0-5]),s?)){3})|(((([1-9]?d(.d+)?)|100|(.d+))%,s?){3}))|(((((1?[1-9]?d)|10d|(2[0-4]d)|25[0-5])s){3})|(((([1-9]?d(.d+)?)|100|(.d+))%s){3}))/s)((0?.d+)|[01]|(([1-9]?d(.d+)?)|100|(.d+))%))$/i

Neste uttrykk er svært lik den pervious, men tre tilfeller av heltall (((((1?[1-9]?d)|10d|(2[0-4]d)|25[0-5]), s?){3})) eller prosenter ((((([1-9]?d(.d+)?)|100|(.d+))%, s?){3})), pluss komma valgfri plass er sjekket. Ellers ser det ut for det samme, men med mellomrom som skilletegn, pluss en skråstrek og plass (/\s) etter de blå. Ved siden av det er ((0?.d+)|[01]|(([1-9]?d(.d+)?)|100|(.d+))%) hvor vi godtar flyter med eller uten innledende 0 ((0?.d+)), 0 eller 1 ([01]) på punktum, eller 0-100% ((([1-9]?d(.d+)?)|100|(.d+))%).

Hex med Alpha
// #rgb/#rrggbb
/^#([da-f]{3}){1,2}$/jeg
// #rgba/#rrggbbaa
/^#([da-f]{4}){1,2}$/jeg

For både hex—med og uten alfa—forekomster av tallene eller bokstavene a–f ([da-f]) er akseptert. Deretter én eller to forekomster av dette er regnet for enten kort eller longhand verdier som følger med (#rgb-eller #rrggbb). Som en illustrasjon, og vi har denne samme kort mønster: /^#([da-f]{n}){1,2}$/jeg. Bare endre n 3 eller 4.

HSL og HSLA
// HSL
/^hsl(((((([12]?[1-9]?d)|[12]0d|(3[0-5]d))(.d+)?)|(.d+))(deg)?|(0/0?.d+)turn|(([0-6\.d+)?)|(.d+))rad)((,s?(([1-9]?d(.d+)?)|100|(.d+))%){2}|(s(([1-9]?d(.d+)?)|100|(.d+))%){2}))$/jeg
// HSLA
/^hsla(((((([12]?[1-9]?d)|[12]0d|(3[0-5]d))(.d+)?)|(.d+))(deg)?|(0/0?.d+)turn|(([0-6\.d+)?)|(.d+))rad)(((,s?(([1-9]?d(.d+)?)|100|(.d+))%){2},s?)|((s(([1-9]?d(.d+)?)|100|(.d+))%){2}s/s))((0?.d+)|[01]|(([1-9]?d(.d+)?)|100|(.d+))%))$/i

Etter ( i både uttrykk for HSL og HSLA, dette stor del er for kulør:

((((([12]?[1-9]?d)|[12]0d|(3[0-5]d))(.d+)?)|(.d+))(deg)?|(0/0?.d+)turn|(([0-6\.d+)?)|(.d+))rad)

([12]?[1-9]?d) dekker 0-99, 110-199, og 210-299. [12]0d dekker 110-109 og 200-209. Deretter (3[0-5]d) tar seg av 300-359. Årsaken til denne inndelingen av områdene er lik som heltall i rgb() syntaks: kjennelse ut nuller kommer først og verdier som er større enn den maksimale. Siden fargetoner kan være flyttall, den første (.d+)? er for det.

Ved | etter nevnte delen av koden, den andre (.d+) er for flyter uten en innledende null.

Nå la oss gå opp et nivå og dechiffrere den neste lille boksen:

(deg)?|(0/0?.d+)slå|(([0-6\.d+)?)|(.d+))rad

Denne inneholder etiketter som vi kan bruke for hue—grader, slår, eller radianer. Vi kan omfatte alle eller ingen av deg. Verdier som i sin tur må være under 1. For radianer, kan vi ikke akseptere noen flyte mellom 0-7. Vi vet imidlertid at en 360° sving er 2π, og det stopper omtrent på 6.28. Du tror kanskje 6.3 og over bør ikke bli akseptert. Fordi 2π er en irrasjonell nummer, det ville bli for rotete for dette eksemplet for å prøve å tilfredsstille alle desimal gitt av JavaScript-konsollen. I tillegg har vi denne kodebiten i vår HSLTo_() fungerer som et ekstra lag av sikkerhet hvis fargetoner 360° eller over var til å skje:

// Holde hue brøkdel av 360 hvis du slutter opp over
hvis (h >= 360)
h %= 360;

Nå la oss gå opp et nivå og dechiffrere den andre del:

(, s?(([1-9]?d(.d+)?)|100|(.d+))%){2}

Vi teller to forekomster av komma-plass-prosenter for metning og lyshet (plass valgfritt). I gruppen etter , s?, vi tester for verdier 0-99 med eller uten desimaler (([1-9]?d(.d+)?)), nøyaktig 100, eller flyter under 1 uten innledende 0) ((. d+)).

Siste del av HSL uttrykk, før avslutningen ()$/jeg), er et tilsvarende uttrykk hvis parkeringsplasser er den eneste separator:

(\s(([1-9]?d(.d+)?)|100|(.d+))%){2}

s er i begynnelsen i stedet for , s?. Så i HSLA uttrykk, det samme del er inne i en annen gruppe med , s? etter sin {2}.

((, s?(([1-9]?d(.d+)?)|100|(.d+))%){2},s?)

Som teller komma-plass mellom letthet og alfa. Så hvis vi har mellomrom som skilletegn, må vi se etter en plass-slash-plass (s / s) etter telle to forekomster av plass og en prosent.

((\s(([1-9]?d(.d+)?)|100|(.d+))%){2}s / s))

Etter at vi har denne til venstre for å sjekke alfa-verdien:

(((0?.d+)|[01])|(([1-9]?d(.d+)?)|100|(.d+))%)

Passer for (0?.d+) inkluderer flyter under 1 med eller uten innledende 0, 0 eller 1 for [01], og 0-100%.

Konklusjon

Hvis din nåværende utfordring er å konvertere fra ett fargerom til et annet, du har nå fått noen ideer om hvordan å nærme seg det. Fordi det ville være slitsomt å gå gjennom konvertering av hver farge plass noensinne oppfunnet i ett innlegg, diskuterte vi den mest praktiske og nettleser som støttes nå. Hvis du ønsker å gå utover støttes fargerom (si CMYK, XYZ, eller CIE L*a*b*), EasyRGB) gir et fantastisk sett med kode-klar formler.

For å se alle konverteringer vist her, har jeg satt opp en CodePen demo som viser innganger og utganger i en tabell. Du kan prøve forskjellige farger i linjer 2-10 og se den komplette funksjoner i JavaScript-panelet.

Se Pen Farge Konvertering av Jon Kantner (@jkantner) på CodePen.