Mischen Sie eine HSLA-Farbe mit Weiß und konvertieren Sie sie mit Chroma.js in Nicht-Alpha-HSL

Dec 10 2020

Ich habe ein Designsystem mit vielen, vielen Farben. Ich habe eine Farbtabelle erstellt, in der alle Farben mit jeder anderen Farbe gemischt werden und das Farbkontrastverhältnis (CCR) jeder Kombination ausgegeben wird. Ziel ist es, unzugängliche Farbkombinationen zu kennzeichnen.

Ich verwende Chroma.js, um die Farben zu manipulieren und die CCRs auszugeben. Es funktioniert hervorragend mit dem Großteil meiner HSL-definierten Farben.

Das Problem tritt auf, wenn mein Designsystem eine Farbe mit einem Alphakanal verwendet. Es ist problematisch zu bestimmen, wie sich ein Farbpaar mit CCR verhält, wenn eine oder beide transparent sind. Ich versuche ein paar verschiedene Dinge, um eine HSLA-Farbe mit Weiß zu mischen oder zu mischen und dann die Kontrastfunktion darauf auszuführen. Hier ist ein Ausschnitt von dem, was ich tue:

// 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

Die Ergebnisse werden mit dieser Grafik visualisiert, die ich zusammengestellt habe. Links sind zwei Farben mit einer Überlagerung in der Mitte. In Adobe Illustrator habe ich 25% Transparenz für die Bräunungsfarbe und einen "normalen" Mischmodus verwendet. Ich habe dasselbe in CSS gemacht und es dann per Screenshot aufgenommen und dann die resultierende Farbmischung in Photoshop gemessen. Rechts sehen Sie die Ausgaben der Chroma-Farbfunktionen:

Nachdem ich versucht habe, die Optionen in Chroma.js zu verstehen, frage ich mich, was ich sonst noch versuchen kann, um meine Ergebnisse näher an die Browserausgabe zu bringen, damit meine CCR-Tests genau sind. Vielen Dank an alle.


Dank der akzeptierten Antwort von @GrahamRitchie sieht meine Ausgabetabelle jetzt so aus. Die kleinen "zusammengesetzten" Beschriftungen zeigen die Farben, die von diesen Funktionen erzeugt wurden, während die Hauptausgabe die transparenten Farben weiterhin übereinander und über den Hintergrund legt.

Antworten

GrahamRitchie Dec 10 2020 at 18:20

Ich weiß nicht, wie ich das mit der von Ihnen erwähnten Bibliothek (Chroma.js) machen soll, aber hoffentlich hilft eine Vanille-JavaScript-Funktion.

Bitte beachten Sie, dass die folgende Funktion immer eine undurchsichtige Hintergrundfarbe voraussetzt, um korrekt zu funktionieren (daher Hintergrund-RGB und Vordergrund-RGBA).

Wenn Sie mit 2 Farben arbeiten müssen, die beide Alphakanäle haben, führen Sie die Funktion zuerst für die Hintergrundfarbe (als Vordergrundfarbe) mit einem weißen Hintergrund aus und kombinieren dann die beiden Farben.

Die Funktion kombiniert auch zwei RGB-Farben. Lassen Sie einfach den Alphakanal weg, wenn Sie Ihre RGB-Farbe übergeben ( 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>