需求背景:
内容区域展示的文字颜色需要根据背景色动态的调整,使之能让用户清晰的辨识到文本内容。
需求分析:
通过加权平均法按照R、G、B三个颜色通道的亮度值之比计算得到背景色的灰色值gray = ( 0.299 * R + 0.587 * g + 0.114 * B ) / 255
,再根据gray
的值选取黑色或白色作为前景色。
实现:
- 获取灰度的方法
function getGrayLevelFromRgb(rgbObj){
return (0.299 * rgbObj.r + 0.587 * rgbObj.g + 0.114 * rgbObj.b) / 255
}
- 颜色字符串转换为颜色对象
function parseColorString(color){
if(color.startsWith('#')){
return parseHexColor(color)
}
if(color.startsWith('rgb')){
return parseRgbaColor(color)
}
if(color === 'transparent'){
return parseHexColor('#00000000')
}
three new Error(`color string error:${color}`)
}
- 16进制颜色字符串解析为颜色对象
function parseHexColor(color){
let hex = color.slice(1) //去除'#'
let a = 1
if(hex.length === 3){
// 如果是3位转为6位
hex = `${hex[0]}${hex[0]}${hex[1]}${hex[1]}${hex[2]}${hex[2]}`
}
if(hex.length === 8){
a = parseInt(hex.slice(6),16) / 255
hex = hex.slice(0,6)
}
const bigInt = parseInt(hex,16)
return {
r:(bigInt >> 16) & 255,
g:(bigInt >> 8) & 255,
b:bigInt & 255,
a,
}
}
- rgb颜色字符串解析为颜色对象
function parseRgbaColor(color){
const arr = color.match(/(\d(.\d+)?)+/g) || []
const res = arr.map(s => parseInt(s,10))
return {
r:res[0],
g:res[1],
b:res[2],
a:parseFloat(arr[3] || 1)
}
}
- 获取灰度等级
function getGrayLevel(color){
const colorObj = parseColorString(color)
return getGrayLevelFromRgb(colorObj)
}
- 显示对应前景色
function getFrontColor(backgroundColor){
return grayLevel > 0.5 ? "#000000b3" : "#ffffff"
}
其他的一些颜色处理方法
- 255颜色值转16进制颜色值
function toHex(n) {
return `${n > 15 ? '' : 0}${n.toString(16)}`
}
- 颜色对象转换为16进制(hex)颜色字符串
function toHexString(colorObj){
const {r,g,b,a = 1} = colorObj
return `#${toHex(r)}${toHex(g)}${toHex(b)}${a === 1 ? toHex(Math.floor(a * 255))}`
}
- 颜色对象转换为rgb颜色字符串
function toRgbString(colorObj){
const {r,g,b} = colorObj
return `rgb(${r},${g},${b})`
}
- 颜色对象转换为rgba颜色字符串
function toRgbaString(colorObj,n = 10000){
const {r,g,b,a = 1} = colorObj
return `rgba(${r},${g},${b},${Math.floor(a * n) / n})`
}