JavaScript
计算颜色的相对亮度,并确定相应的颜色
一、需求内容
需求点:给出一组颜色列表,渲染对应的颜色以及颜色值,但是要保证文本颜色和背景色不冲突,文本颜色保持 black
和 white
两种即可
示例如下:每个模块背景色为当前颜色,文案内容为当前颜色值,文案颜色为当前颜色通过计算后的 ‘black’ 或 ‘white’
二、实现方案
思路
- 背景颜色与文本颜色不能冲突,亮的背景色展示黑色文案,深的背景色展示白色文案
- 使用 YUV 与 RGB 颜色转化公式
- 判断 a 的值,也就是透明度,透明度越小颜色越浅
实现流程
- 先把颜色转化成 rgba
- 根据计算公式 (r * 299 + g * 587 + b * 114) / 1000 将RGB颜色转换为YUV颜色
- 判断计算出来的值在判断 a 的值来确定文本颜色的值
三、代码实现
/**
* 把十六进制颜色值转成 rgba 颜色值
* @param {string} hex
* @returns {string} rgba 颜色值
*/
const hexToRgba = (hex: string): string => {
const rgba = []
hex = hex.replace('#', '').padEnd(8, 'F')
for (let i = 0; i < hex.length; i+=2) {
rgba.push(parseInt(hex.slice(i, i+2), 16))
}
return rgba.reduce((prev, item, index) => {
return prev += index >= rgba.length - 1 ? Number((item / 255).toFixed(2)) : `${item}, `
}, 'rgba(') + ')'
}
/**
* 计算文本颜色值
* @param {string} hexColor
* @returns {'black' | 'white'} 文本颜色值
*/
const determineTextColor = (hexColor: string): 'black' | 'white' => {
// 将十六进制颜色值转换为 RGB 格式
const rgbColor = hexToRgba(hexColor);
// 获取颜色的 RGB 分量
const [r, g, b, a] = (rgbColor.match(/\d+(\.\d+)?/g) || []).map(Number);
// 计算颜色的相对亮度
const brightness = (r * 299 + g * 587 + b * 114) / 1000;
// 根据相对亮度确定文本颜色
return brightness > 125 ? 'black' : (a < 0.4 ? 'black' : 'white')
}
四、案例效果展示
案例
const colorList = [
"#FAFAFAA6",
"#000000FF",
"#000000EE",
"#000000AA",
"#00000088",
"#00000066",
"#00000033",
"#00000022",
"#00000011",
"#00000000",
"#333333FF",
"#FFFFFFFF",
"#FFFFFFEE",
"#FFFFFFBB",
"#FFFFFFAA",
"#FFFFFF99",
"#FFFFFF88",
"#FFFFFF66",
"#FFFFFF33",
"#FFFFFF22",
"#FFFFFF11",
"#344258FF",
"#4CAF50DE",
"#364FBBFF",
"#00000040",
"#FF4D4FFF",
"#233494FF",
"#0505050F",
"#00000005",
"#E7E8EAFF",
"#F5F7FAFF",
"#7A7A7AFF",
"#1677FFFF",
"#69B1FFFF",
"#0958D9FF",
"#00000014",
"#0000001E",
"#0000000C",
"#52C41AFF",
"#FAAD14FF",
"#00000073",
"#0000000F",
"#001529FF",
"#002140FF",
"#FFFFFF33",
"#722ED1FF",
"#13C2C2FF",
"#EB2F96FF",
"#F5222DFF",
"#FA8C16FF",
"#FADB14FF",
"#FA541CFF",
"#2F54EBFF",
"#A0D911FF",
"#000000D9",
"#ADBBE0FF",
"#5A71C7FF",
"#FFF2F0FF",
"#FFFFFFA6",
"#FFFFFF00",
"#FFFFFF40",
"#FF7875FF",
"#000C17FF",
"#0543C014",
"#0000000A",
"#FFA39EFF",
"#FF26050F",
"#FFD666FF",
"#FFD70519",
"#D9363EFF",
"#00000026",
"#DDE2EDFF",
"#F5F5F5FF",
"#F0F0F0FF",
"#D9D9D9FF",
"#000FFFFF",
"#000000A6",
"#EBF0FAFF",
"#8196D4FF",
"#F6FFEDFF",
"#D9F7BEFF",
"#B7EB8FFF",
"#95DE64FF",
"#389E0DFF",
"#73D13DFF",
"#FFF1F0FF",
"#FFCCC7FF",
"#FFFBE6FF",
"#FFF1B8FF",
"#FFE58FFF",
"#D48806FF",
"#FFC53DFF",
"#E6F4FFFF",
"#BAE0FFFF",
"#91CAFFFF",
"#4096FFFF",
"#FAFAFAFF",
"#EDEDEDFF",
"#E0E0E0FF",
"#D4D4D4FF",
"#C7C7C7FF",
"#A1A1A1FF",
"#545454FF",
"#2E2E2EFF"
]
let html = '<ul>'
colorList.forEach((item) => {
const data = determineTextColor(item)
html += `<li style="background: ${item}; color: ${data}; border: 1px solid ${data};">${item}</li>`
})
html += '</ul>'
document.body.innerHTML = html