Смешайте цвет HSLA с белым и преобразуйте его в не-альфа HSL с помощью Chroma.js
У меня есть система дизайна с множеством цветов. Я создал таблицу цветов, в которой все цвета смешиваются со всеми остальными цветами, и выводится коэффициент цветовой контрастности (CCR) каждой комбинации. Цель состоит в том, чтобы отметить недоступные сочетания цветов.
Я использую Chroma.js для управления цветами и вывода CCR. Он блестяще работает с большинством моих цветов, определенных HSL.
Проблема возникает, когда моя дизайн-система использует цвет с альфа-каналом. Определение того, как пара цветов работает с CCR, когда один или оба из них прозрачны, проблематично. Я пробую несколько разных вещей, чтобы смешать или смешать цвет HSLA с белым, а затем запустить на нем функцию контраста. Вот отрывок из того, что я делаю:
// 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
Результаты визуализируются с помощью этого рисунка, который я собрал. Слева два цвета с наложением их посередине. В Adobe Illustrator я использовал 25% прозрачность для коричневого цвета и "нормальный" режим наложения. Я сделал то же самое в CSS, затем сделал снимок экрана, а затем измерил полученное цветовое сочетание в Photoshop. Справа показаны выходы цветовых функций Chroma:

Попробовав то, что я понимаю как параметры в Chroma.js, мне интересно, что еще я могу попытаться приблизить свои результаты к выходным данным браузера, чтобы мои тесты CCR были точными. Спасибо всем.
Благодаря принятому ответу от @GrahamRitchie моя таблица результатов теперь выглядит так. Маленькие «составные» метки показывают цвета, созданные этими функциями, в то время как основной вывод по-прежнему накладывает прозрачные цвета друг на друга и на фон.

Ответы
Я не знаю, как это сделать с помощью упомянутой вами библиотеки (Chroma.js), но, надеюсь, вам поможет ванильная функция JavaScript.
Обратите внимание, что приведенная ниже функция всегда предполагает, что для правильной работы всегда используется непрозрачный цвет фона (следовательно, фоновый RGB и передний план RGBA).
Если вам нужно работать с двумя цветами, у обоих есть альфа-каналы, вы должны сначала запустить функцию на цвете фона (как цвет переднего плана) с белым фоном, а затем объединить два цвета.
Функция также объединит два цвета RGB, просто пропустите альфа-канал при передаче вашего цвета 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>