Zmieszaj kolor HSLA z białym i przekonwertuj na HSL inny niż alfa za pomocą Chroma.js
Mam system projektowania z wieloma, wieloma kolorami. Stworzyłem tabelę kolorów, w której wszystkie kolory są mieszane z każdym innym kolorem, a współczynnik kontrastu koloru (CCR) każdej kombinacji jest wyświetlany. Celem jest oznaczenie niedostępnych kombinacji kolorów.
Używam Chroma.js do manipulowania kolorami i wyświetlania CCR. Świetnie współpracuje z większością moich kolorów zdefiniowanych przez HSL.
Problem pojawia się, gdy mój system projektowania używa koloru z kanałem alfa. Określenie, jak para kolorów zachowuje się z CCR, gdy jeden lub oba z nich są przezroczyste, jest problematyczne. Próbuję kilku różnych rzeczy, aby zmieszać lub zmieszać kolor HSLA z bielą, a następnie uruchomić na tym funkcję kontrastu. Oto fragment tego, co robię:
// where either foreground or background has an alpha value present less than 1
var background = chroma.mix(background, '#fff', 1, 'lab').css();
var foreground = chroma.mix(foreground, background, 1, 'lab').css();
var ccr = chroma.contrast(foreground, background);
// lab gets the closest but not the same as the way CSS overlays colors
Wyniki są wizualizowane za pomocą złożonej przeze mnie grafiki. Po lewej stronie znajdują się dwa kolory z ich nałożeniem pośrodku. W programie Adobe Illustrator użyłem 25% przezroczystości koloru opalenizny i „normalnego” trybu mieszania. Zrobiłem to samo w CSS, a następnie wykonałem zrzut ekranu, a następnie zmierzyłem wynikową mieszankę kolorów w Photoshopie. Po prawej stronie znajdują się wyjścia funkcji koloru Chroma:

Po wypróbowaniu tego, co rozumiem jako opcje w Chroma.js, zastanawiam się, co jeszcze mogę spróbować, aby moje wyniki były bliżej wyników przeglądarki, aby moje testy CCR były dokładne. Dziękuje wszystkim.
Dzięki zaakceptowanej odpowiedzi od @GrahamRitchie moja tabela wyjściowa wygląda teraz tak. Małe „złożone” etykiety pokazują kolory, które zostały wyprodukowane przez te funkcje, podczas gdy główny wynik nadal nakłada przezroczyste kolory na siebie i na tło.

Odpowiedzi
Nie wiem, jak to zrobić ze wspomnianą biblioteką (Chroma.js), ale mam nadzieję, że pomoże w tym zwykła funkcja JavaScript.
Należy pamiętać, że poniższa funkcja zawsze zakłada nieprzezroczysty kolor tła, aby działać poprawnie (stąd RGB tła i RGBA pierwszego planu).
Jeśli musisz pracować z 2 kolorami, z których oba mają kanały alfa, uruchom funkcję najpierw na kolorze tła (jako kolor pierwszego planu) z białym tłem, a następnie połącz oba kolory.
Funkcja połączy również dwa kolory RGB, po prostu pomiń kanał alfa podczas przekazywania koloru RGB ( convertToRGB({r,g,b}, {r,g,b})
)
function convertToRGB(frontRGBA, backgroundRGB){
var rtrn = {};
//allows the function to just accept a front colour and assume the background is a plain white.
backgroundRGB = backgroundRGB || {r:255,g:255,b:255};
//allows a RGB value to be passed in assuming full alpha channel.
frontRGBA.a = frontRGBA.a || 1;
//normalise the alpha channel across the foreground and background.
rtrn.r = ((1 - frontRGBA.a) * backgroundRGB.r) + (frontRGBA.a * frontRGBA.r);
rtrn.g = ((1 - frontRGBA.a) * backgroundRGB.g) + (frontRGBA.a * frontRGBA.g);
rtrn.b = ((1 - frontRGBA.a) * backgroundRGB.b) + (frontRGBA.a * frontRGBA.b);
//just check that we don't end up with a value greater than 255 for any channel.
rtrn.r = (rtrn.r > 255) ? 255 : rtrn.r;
rtrn.g = (rtrn.g > 255) ? 255 : rtrn.g;
rtrn.b = (rtrn.b > 255) ? 255 : rtrn.b;
return rtrn;
}
var backgroundRGB = {r:165,g:193,b:211};
var frontRGBA = {r:210,g:203,b:178,a:0.25};
//used for example
var rgb = convertToRGB(frontRGBA, backgroundRGB);
document.querySelector(".output").style.background = "rgb(" + rgb.r + "," + rgb.g + "," + rgb.b + ")";
document.querySelector(".output").innerHTML = "Output<br/>R:" + rgb.r + "<br/>G:" + rgb.g + "<br/>B:" + rgb.b;
.container div{
width: 200px;
height: 200px;
float: left;
}
.div1{
background: rgba(165,193,211,1);
}
.div2{
background: rgba(210,203,178,0.25);
}
<div class="container">
<div class="div1">Background<br/>R:165<br/>G:193<br/>B:211<br/>A:1</div>
<div class="output">Output</div>
<div class="div2">Foreground<br/>R:210<br/>G:203<br/>B:178<br/>A:0.25</div>
</div>