在RGB色彩模式下反色比较简单,我针对此模式中的RGB颜色表示法进行反色计算,分享一些计算上的技巧 (HEX颜色表示法理论上也是相通的)。
取反色值非常简便,使用255减去三色即可,操作一步到位,如下所示:
rgb(a,b,c); //原值
rgb(255-a,255-b,255-c) //反色
但是在页面的实际应用中,我们通常拿不到rgb三值,而是获取到"rgb(a,b,c)"
整体的字符串,那么需要三个步骤
- 拆解 拆解出rgb值
- 反色 计算出反色值
- 合并 组装计算结果
首先给出拆解的思路,按照常规的想法,以截取的方式拆解出rgb值:
let rgb = 'rgb(25,100,72)'
//查找颜色值的起始点
const redPoint = rgb.indexOf(',')
const greenPoint = rgb.indexOf(',', redPoint + 1);
const bluePoint = rgb.indexOf(',', redPoint + 1);
//截取出颜色值
let r = rgb.substring('4', redPoint)
let g = rgb.substring(redPoint + 1, greenPoint)
let b = rgb.substring(bluePoint + 1, rgb.indexOf(')'))
//反色
r = 255 - Number(r);
g = 255 - Number(g);
b = 255 - Number(b);
//组装结果
rgb = 'rgb(' + r + ',' + g + ',' + b + ')'
思路非常清晰,但是我们发现,拆解过程较长,需要逐个使用indexOf
查找颜色值的起始点,然后用substring
截取出颜色值,较为不便,其实这一过程可以用split
函数进行优化:
let rgb = 'rgb(25,100,72)'
//拆分颜色值
rgb = rgb.substring(4, rgb.lastIndexOf(')')).split(',')
//分解出颜色值
let r = rgb[0]
let g = rgb[1]
let b = rgb[2]
此时,既然拿到拆分后的数组,有必要怀疑分解出颜色值这一过程的必要性,因为我们可以直接对数组使用map
函数进行循环,在过程中反转颜色值,最后使用join
提取出结果
let rgb = 'rgb(25,100,72)'
//拆分颜色值
rgb = rgb.substring(4, rgb.lastIndexOf(')')).split(',')
//循环计算并合并结果
rgb = rgb.map((item) => 255 - Number(item)).join(',')
rgb = 'rgb(' + rgb + ')'
此时只需要两个步骤了,那么我们便逐个分析,拆分颜色值是否还有更简便的方法,截取出有效的颜色值其实不如过滤掉的无效字符,我认为可以用replace
的正则替换代替substring
rgb = rgb.replace(/[rgb\(\)]/g, '').split(',')
显然这一过程更加简洁,那么循环并合并结果能否简便呢,其实reduce
便可总结map
,join
的操作,总结如下
let rgb = 'rgb(25,100,72)'.replace(/[rgb\(\)]/g, ',').split(',').reduce((e, c) =>
c.length ? e + "," + (255 - Number(c)) : e).replace(',', 'rgb(') + ')'