【发布时间】:2021-12-29 19:20:50
【问题描述】:
对于我正在开发的模组,我想结合播放器的主题颜色并使用它们来生成 UI 元素。但是,我遇到了一个问题,即并非所有颜色主题都具有提供 good contrast ratio 的颜色,如 Web Content Accessibility Guidelines (WCAG) 2.1 的 1.4.3 Contrast (Minimum) 中所述。
我目前可以通过以下方式检查对比度:
float RelativeLuminance(Color color)
{
float ColorPartValue(float part)
{
return part <= 0.03928f ? part / 12.92f : Mathf.Pow((part + 0.055f) / 1.055f, 2.4f);
}
var r = ColorPartValue(color.r);
var g = ColorPartValue(color.g);
var b = ColorPartValue(color.b);
var l = 0.2126f * r + 0.7152f * g + 0.0722f * b;
return l;
}
private float ColorContrast(Color a, Color b)
{
float result = 0f;
var La = RelativeLuminance(a) + 0.05f;
var Lb = RelativeLuminance(b) + 0.05f;
result = Mathf.Max(La, Lb) / Mathf.Min(La, Lb);
return result;
}
我使用找到的颜色对比来确定初始文本颜色是否足够好。
public Color GetContrastingColors(Color backgroundColor, Color textColor)
{
Color contrastColor;
// See if we have good enough contrast already
if (!(ColorContrast(backgroundColor, textColor) < 4.5f))
{
return textColor;
}
Color.RGBToHSV(textColor, out var textH, out var textS, out var textV);
Color.RGBToHSV(backgroundColor, out var bgH, out var bgS, out var bgV);
// Modify textV by some value to provide enough contrast.
contrastColor = Color.HSVToRGB(textH, textS, textV);
return contrastColor;
}
但是,我不确定如何调整颜色以使文本颜色变亮(或变暗)以达到 4.5:1 的对比度。最初,我正在考虑将亮度和对比度方程的代数工作到sRGB 值乘以某个值 X 的程度。不过我记得 HSV,调整颜色的亮度对我来说似乎要简单得多。问题是,我不确定如何比较 2 种 HSV 颜色的对比度,更不用说使用它们的值来操纵颜色的亮度以达到所需的对比度。
我目前的想法是做这样的蠢事:
float targetL;
bool brighter = false;
var backL = RelativeLuminance(backgroundColor);
var textL = RelativeLuminance(textColor);
var ratio = 4.5f;
// Try to go in the direction of brightness originally.
if (textL > backL)
{
targetL = ((backL + 0.05f) * ratio) - 0.05f;
brighter = true;
if (targetL > 1f)
{
targetL = ((backL + 0.05f) / ratio) - 0.05f;
brighter = false;
}
}
else
{
targetL = ((backL + 0.05f) / ratio) - 0.05f;
if (targetL > 0f)
{
targetL = ((backL + 0.05f) * ratio) - 0.05f;
brighter = true;
}
}
Color adjustedColor = textColor;
while ((!brighter && textL > targetL) || (brighter && textL < targetL))
{
Color.RGBToHSV(adjustedColor, out var textH, out var textS, out var textV);
textV += brighter ? 0.01f : -0.01f;
adjustedColor = Color.HSVToRGB(textH, textS, textV);
textL = RelativeLuminance(adjustedColor);
}
contrastColor = adjustedColor;
但这并不是很有效,那么我该如何操作文本颜色以使其“保持不变”但提供足够的对比度?
编辑:
为了给我正在尝试做的事情提供更多背景信息,假设我有以下 4 种颜色作为玩家的主题。
就 HTML 代码而言,就是:
| #32263d | #3d1c70 |
| #7347b6 | #320d68 |
在为他们创建 UI 时,我想从他们的主题中加入其中 2 种颜色。但是,并非所有这些都易于区分,您可以在此处查看本例中的各种对比:
现在每个主题都包含较深和较浅的颜色,就像本示例中的中间 2 行一样,但也像本示例一样,最终用户可能无法始终阅读它们的对比度。继续看示例,在本例中,我们将使用 #32263d 和 #7347b6 来构建我们的 UI。
虽然我可以尝试随机创建类似的紫色阴影,但我希望使其尽可能接近原始颜色并使其变亮。我们可以在这里看到它在不同层次的光线下的样子:
如果我们将#7347b6 设置为#a163ff 的最大亮度,我们现在得到以下一对:
虽然比以前更好,但这仍然只是 3.88 : 1 的对比度。所以现在我想缩小#32263d 的亮度。如果我们把它减少到#251B2D,我们就会得到这样的结果:
这两种新颜色的颜色对比度为 4.51 : 1。
现在,我可以手动浏览每个主题,但考虑到它们的数量,我更愿意编写一个算法来动态生成更新的颜色。
【问题讨论】:
-
“我想合并播放器的主题颜色并使用它们来生成 UI 元素。但是,我遇到了一个问题,并非所有颜色主题都有提供良好的颜色对比度” - 你说的是"Complementary - Two colors that are on opposite sides of the color wheel. This combination provides a high contrast and high impact color combination – together, these colors will appear brighter and more prominent."吗?
-
@MickyD 不,我指的是玩家对象主题中的一对颜色,例如
new Color(0.1647059f, 0.3098039f, 0.5843138f, 1f)和new Color(0.2196078f, 0.254902f, 0.3098039f, 1f)。它们不一定是互补的,也不一定如此。 -
快速查看Adobe Color - Accessibility Tools - Contrast Checker 表明您选择
#2A4E95和#37414E只需将背景 颜色更改为#A8C5E9即可。这将实现 4.5:1 的对比度。听起来您的问题只是如何计算给定文本颜色的可访问性背景颜色。 Possibility relevant -
@MickyD “听起来你的问题只是如何计算给定文本颜色的可访问性背景颜色。”是/否。我可以这样做,但这只是变相的相同问题(我仍然需要根据另一种颜色计算颜色)。我的问题是我试图保持“相同”的颜色,只需在 HSV 比例上调整它的亮度(与我将 RGB 分量乘以一个因子
x的结果相同)。更改为#A8C5E9实际上会以与我的意图不同的方式调整它们。 (1/2) -
举个例子,如果给我
#80b9ff和#5b6b80(对比度为2.67),我想降低#5b6b80的亮度直到它变成#505d70(对比度为 4.55,#80b9ff)。它仍然具有相同的色调和饱和度,只是亮度不同。现在,我扔在那里的这些颜色只是游戏中内置的几种颜色。我无法修改它们,所以我需要使用它们。我的问题是如何调整它们? (2/2)
标签: c# unity3d colors accessibility