首页 > 解决方案 > 将 HSLA 颜色与白色混合并使用 Chroma.js 转换为非 alpha HSL

问题描述

我有一个有很多很多颜色的设计系统。我创建了一个颜色表,其中所有颜色都与其他颜色混合,并输出每种组合的颜色对比度 (CCR)。目标是标记无法访问的颜色组合。

我正在使用 Chroma.js 来操作颜色并输出 CCR。它与我的大部分 HSL 定义的颜色完美搭配。

当我的设计系统使用带有 Alpha 通道的颜色时,麻烦就来了。当一对颜色中的一个或两个都是透明的时,确定一对颜色如何与 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

结果用我放在一起的这张图进行了可视化。左边是两种颜色,中间有叠加。在 Adob​​e Illustrator 中,我在棕褐色上使用了 25% 的透明度和“正常”混合模式。我在 CSS 中做了同样的事情,然后截屏,然后在 Photoshop 中测量了生成的颜色混合。右侧是色度颜色函数的输出:

不同程序化混合模式的可视化

尝试了我理解的 Chroma.js 中的选项后,我想知道我还能尝试什么让我的结果更接近浏览器输出,以便我的 CCR 测试准确。谢谢大家。


感谢@GrahamRitchie 接受的答案,我的输出表现在看起来像这样。小的“复合”标签显示了这些函数产生的颜色,而主要输出仍然将透明颜色叠加在彼此和背景上。

此代码有助于支持的巨型表的 Samepl 输出

标签: javascriptcolorsaccessibilityrgba

解决方案


我不知道如何使用您提到的库(Chroma.js)来做到这一点,但希望一个普通的 JavaScript 函数会有所帮助。

请注意,以下函数始终假定不透明背景颜色才能正常工作(因此背景 RGB 和前景 RGBA)。

如果您需要使用两种都具有 alpha 通道的颜色,您将首先在背景颜色(作为前景色)上运行该函数,并使用白色背景,然后将这两种颜色组合起来。

该函数还将结合两种 RGB 颜色,只需在传递 RGB 颜色时省略 alpha 通道 ( 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>


推荐阅读