JavaScript中的颜色转换

特别声明:如果您喜欢小站的内容,可以点击申请会员进行全站阅读。如果您对付费阅读有任何建议或想法,欢迎发送邮件至: airenliao@gmail.com!或添加QQ:874472854(^_^)

图解CSS系列的《CSS 颜色》一文中介绍了CSS中颜色的使用。到目前为止,给Web元素设置颜色的方式有很多种,比如使用颜色名称定义颜色、使用#RGB(或#RRGGBB)、#RGBA(或#RRGGBBAA)、hsl()(或hsla())、hwb()lab()lch()等。在CSS的颜色规范的第四版本中的第十五节中,专门介绍了在JavaScript中如何实现颜色不同空间域的转换。在Web的开发中,有的时候难免离不开使用JavaScript来操作颜色,接下来在这篇文章中,我们主要和大家一起来聊聊JavaScript中颜色空间的转换应该如何实现。

原则上说,任意两种颜色模式之间的转换都可以通过JavaScript脚本来实现

颜色世界中的一些基本概念

从《CSS 颜色》中我们或多或少的了解到,在Web的颜色世界中和印刷世界(或者说现实生活)中,颜色是丰富多彩的,除了能点缀我们的生活之外,同样也能丰富Web的世界。在Web环境中,描述颜色有几个概念是缺少不了的,即 颜色模型颜色空间颜色配置文件。简单地说,编码的时候,这几个概念是非常重要的。

颜色模型

不知道你有没有安装打印机墨盒的经验。如果有的话,你应该知道大多数的打印机都有四种颜色的墨盒,对应的就是我们常说的*CMYK颜色模型:

而在设计软件或Web使用中,CMYK对于大家来说,使用的并不多,反而是RGB模型更多一些。事实上,不管是CMYK还是RGB都被称为颜色模型

简单地说,颜色模型是一种将色谱描述为多维模型的可视化方法。大多数现代的色彩(彩色)模型都有三个维度(比如我们熟悉的RGB模式),因此也被描述为 3D形状,但也有的色彩模型有更多的维度,比如CMYK。对于很多开发者而言,较为熟悉的是RGBHSVHSL颜色模型,它们在当前的数字设计工具和编程语言中都很流行。这些颜色模型都使用相同的RGB原色(即红、绿、蓝):

而时至今日,除了上面所说的几种颜色模型,还有一种新的颜色模型HCL,该模型的配色能更方便地达到高可用性(Accessibility),对人眼更加友好。接下来简单的了解来了解这几种颜色模型。

RGB颜色模型

色彩(或颜色)是人类大脑对事物的一种主观感觉,为了将这种感性进行理性描述,数学家们创建了 RGB 颜色模型。

RGB颜色模型是一种三维的颜色模型,即通过三个数的组合(颜色色值)来表述某一种特定的颜色。简单地说,就是使用红色绿色蓝色混合在一起产生一种特定的颜色。当在这些维度中定义颜色时,我们必须知道颜色光谱中的颜色序列,例如,100%的红色和绿色混合产生黄色。RGB颜色模型通常被描述为一个立方体,通过在三维空间中将红色、绿色和蓝色维度映射到xyz轴.

三维坐标系中的xyz轴分别对应的是RGB颜色模型中的RedGreenBlue。根据“空间直角坐标系”相关的知识,我们可以获知RGB(x, y, z)将构建的每个颜色点,都对应于立方体中的某个点,也就是说每一种颜色都被包含在我们的色彩空间之内。下面的录屏就是用来演示这一点,其中所有可能的颜色混合都表示在立方体的范围内。

RGB颜色模型在编码中创建的颜色并不是特别直观,比如rgb(230, 33, 120),对于这样的rgb()函数中的xyz坐标值,开发者并无法直观的知道它具体代表的是什么颜色。特别是,前景色(color)和背景色(background-color)要实现互补时,更难于直观描述。

HSL颜色模型

在介绍RGB颜色模型的时候提到过,使用rgb(x, y, x)(比如rgb(230, 33, 120))描述的颜色,更多的时候是适用于告诉计算机该如何做色彩的展示,但对于设计师或者开发者来说并不怎么友好,他们一般不会这样去设计自己想要的颜色。

不管是设计师还是开发者,在实际中也并不会这样去使用颜色(设置颜色),更多的是通过拾色器(比如设计师使用的设计软件中的拾色器,开发者在设计软件中的拾色器或者浏览器开发者工具中的拾色器)。比如:

既然RGB颜色模式不易于直观的描述(表达颜色),那么我们就可以考虑使用其他的颜色模式,比如说HSL颜色模式,即 Hue (色相)、Saturation(饱和度)和 Lightness(明度,也有人称亮度)。在众多的设计软件中,调色器也具有HSL颜色模型,往往是分为两个部分组成:一个二维的调色窗口,然后配合一个一维的调色轴,以此组合成为三维调色器。

事实上,HSL模型描述的颜色也可以用RGB颜色模型来描述,也就是说,HSL颜色模型中的每一个色彩都能和RGB颜色模型中的色彩相对应,换句话说,HSL颜色模型中的空间直角坐标系内的每一个坐标点,都会对应到RGB颜色模型中的空间直角坐标系中。比如下图所示:

你可能已经发现了,在RGB颜色模型的坐标系空间中(上图的立方体),超靠近顶点位置(xyz轴的交叉点o),颜色也就越深,o点是纯黑色的;反之,远离o坐标点的位置,颜色也就越浅(o点的对角点a位置是纯白色)。而oa连线中的每一个点,其rgb(x, y, z)的值都是x = y = z,而且该条线中的每一个点都是从纯黑到纯白不同程度的灰色。

如果调整RGB直角坐标系构成的立方体角度,让oa直线垂直于设备的屏幕,就会看到下图这样的形状:

如果将这个六边形拉伸变成一个圆形,它就成为我们常见的一个色盘。其中圆形中每个角度对应的颜色就是HSL中的 H(色相),从圆心到圆周的变化,代表的是 S(饱和度),从o点到a点的变化,代表的是 L(亮度)。

回到拾色器中,它就变成:

HSL颜色模型中,我们可以用一个立柱体来描述,会更清晰:

HSV颜色模型

HSV颜色模型和HSL颜色模型极其相似,也是一个圆柱形颜色模型。

其中H指的也是色相,其中0360度代表的是红色,60度代表黄色,120度代表绿色,180度代表青色、240代表蓝色,300度代表洋红。这几个颜色也常被称为色相环中的六大主色

S也是用来控制颜色的使用量。100%饱和度折颜色将是最纯的颜色,而0%饱和度将产生灰色。而V有点类似于HSL中的L,主要用来控制颜色的亮度。0%亮度的颜色是纯黑色,而100%亮度的颜色没有黑色混入到颜色中。

注意,HSV也常常被称为HSB

HSV颜色模型中,三个维度是相互依赖的。如果颜色的V维度设置为0%HS数量并不重要,因为颜色将是黑色。同样地,如果颜色的S设置为0%H也没有关系,因为没有使用颜色。HSV中的H(色相)展开的话也是一个圆环,每个角度对应的是不同的颜色。

HSL一样,下图可以很形象的描述颜色:

HWB颜色模型

HWB颜色模型和前面的HSLHSV(或HSB)类似,也可以用柱形来描述:

HWBHue Whiteness Blackness三个单词的首字母缩写,该颜色模型是由@Alvy Ray Smith引入的一种颜色模型。创建该颜色模型的初衷主要是用来作为HSL(或HSV)颜色模型的替代方案。这样做可以让设计师或开发者设计颜色更为简单,正如@Alvy Ray Smith所说:

使用HWB颜色模型,你所要做的就是选择一种色调(H),用白色让其更亮,用黑色让其变得更黑

也就是说,HWB中的H和前面提到的HSLHSV中的H是相同的,都是用色相环来描述颜色。而WB分别代表的是添加到颜色中白色和黑色所占程度,一般都是用百分比来表示。如果要让一个颜色(色相环中对应的某一颜色)变亮,就需要增加白色所占份量,反之,如果想让颜色变暗,就是相应的增加黑色所占份量;如果要颜色不饱和,就同时增加白色和黑色的份量。

如果WB两个百分比加起来超过100%,那么就是灰色的,并且这两个属性被规范化,加起来正好是100%。例如hwb(0deg 75% 75%)hwb(0deg 50% 50%)相同。而hwb(0deg 25% 100%)会调整为hwb(0deg 20% 80%)

最后要提到的一点是,HWB颜色模型可以很好的用于用户输入的颜色,但对于非专业人士的话,也较难使用,但对于专业人员来说,更易于理解,因为HWB的概念类似于涂料的混合:

Lab颜色模型

Lab颜色模型是由CIE(国际照明委员会)制定的一种色彩模型。自然界中任何一点色都可以在Lab空间中表达出来,它的色彩空间比RGB空间还要大。另外,这种模式是以数字化方式来描述人的视觉感应,与设备无关,所以它弥补了RGBCMYK模式必须依赖于设备色彩特性的不足。

由于Lab的色彩空要比RGB模式和CMYK模式的色彩空间大。这就意味着RGB以及CMYK所能描述的色彩信息在Lab空间中都能得以映射。Lab颜色模型取坐标Lab,其中L为亮度,a的正数代表红色,a的负数代表绿色;b的正数代表黄色,负数代表蓝色。

HCL颜色模型

我们熟悉用来指定颜色都是定义在sRGB颜色空间中,比如rgbhsl等。但随着科技技术不断的发展,sRGB颜色空间越来越不够使用了。比如现在大多数显示器的色域更接近P3P3的体积比sRGB50%

HCL颜色模型中,相同的坐标数值变化会产生相同的感知色差。这种颜色空间的属性被称为“感知一致性”。换句话说,使用HCL配色能更方便地达到高可用性,对人眼更加友好。

HCL中的H指的是色相,C(Chroma)指的是色距,可以理解为相对饱和度,其中LHSL中的L(高度Lightness)不同,这里的L指的是感知明度(Luminance),也被称为相对感知明度(Relative Luminance),为了和HSL中的L能道区分开,HCL中的LLuma来描述。另外,HCL中的L是基于人眼对亮度对感知而创造的。下图解释了人眼对两种色彩空间的色相环内颜色的明度是如何感知的:

简单地说,HCL中的明度实际上是有意义的

HCL 属于另一种色彩空间,两者不一定能完全匹配。具体表现为:转换后颜色但色相、感知明度均存在,但颜色的色距不一定在 HCL 色彩空间范围内

颜色空间

颜色空间(Color Space是用来组织颜色的方式,换句话说,是用来定义颜色的范围比较知名的颜色空间有sRGBAdobeRGB等。

需要注意的是,尽管颜色模型是抽象的数学概念,但是如果没有相应的颜色空间,就不可能将颜色模型可视化。上面的RGBHSVHSL颜色模型示例都显示在sRGB颜色空间中,因为这是Web的默认颜色空间。

颜色配置文件

数字图像可以通过在其元数据中嵌入颜色配置文件来指定特定的颜色空间。将会告诉任何想要读取图像的程序,像素值是根据特定的颜色空间来表示的,没有颜色配置文件的图像通常被假定为sRGB。为了正确地在多个设备上复制相同的颜色,颜色配置文件非常重要,而且你经常会看到专业的打印服务要求将图像文件设置为特定的颜色空间。如果你曾经将一张图像粘贴到现有的Photoshop项目中,结果发现颜色不对,那么你就是这个问题的受害者(颜色配置文件不匹配)。

如果数字图像使用其具有广泛色域的颜色配置文件,那么它在大多数屏幕上肯定会丢失颜色,因为大多数屏幕只能显示sRGB色域内的颜色。然而,许多新的屏幕支持更大的颜色范围。苹果iMac视网膜屏幕使用了一个称为DCI-P3RGB颜色空间,其色域范围与AdobeRGB(1998)大致相同,但它包含更多的红黄色,并排除了一些绿蓝色。为了空出颜色管理的复杂性,在视网膜屏幕上运行的一些浏览器可能会使没有颜色配置文件的sRGB图像的颜色过度饱和,而其他浏览器会正确地将sRGB像素值转换为DCI-P3

特别声明,对于颜色模型、颜色空间和颜色配置文件几个概念来说,在色彩领域是非常重要的概念,上面这点篇幅无法彻底的将这几个概念彻底介绍清楚。加上自己也是这方面的菜鸟,如果有不对之处,还请路过的大神多多指正

颜色的转换

在《CSS 颜色》一文中,我们了解和学习了在CSS中如何通过不同的方式来描述颜色。不同的方式有不同的优缺点,而且使用姿势也不一样,这里不做阐述。接下来,我们要重点聊的是,如何通过JavaScript实现颜色模式之间的转换,比如rgb()#RRGGBBhsl()rgb()等。如果你对这方面也感兴趣,欢迎继续往下阅读。

RGB和#RRGGBB互转

先来看RGB#RRGGBB两种模式互转。这两种模式都是用红绿蓝来描述一个颜色的,不同的是RGB是十进制数(或百分比),#RRGGBB是十六进制。比如#0798ff可以用rgb(7 152 255)(或者老的语法rgb(7, 152, 255)):

在聊两种模式之间如何通过JavaScript实现转换之前,有一些基础需要简单的了解一下。刚刚也提到过,运用于RGB颜色中的值是我们最熟悉的数字系统,即十进制数字系统

十进制数字系统是一个以10为基数的系统,有十个唯一的字符用于定义这些数字,这十个数字字符就是0 ~ 9

要十进制数字系统中,我们可以把每一个数字都建模成一个能被十的幂除尽:

这就意味着,十进制数字的每个部分都是1101001000或任何10n次方存储桶。我们想要表示的每个相得到的基数为10的数都将位于此模型指定的范围内。

RGB颜色模式中取值范围是0 ~ 255,放到十进制的模型中的话,大致如下:

事实上,十进制数对于我们来说最熟悉不过了,我们不需要这些额外的可视化层或将每个数字映射到适当的10次方的表达式。

接下来,我们来了解一下十六进制数,十六进制数相对于十进制数来说,要更复杂一点。

在十六进制的世界中,表示的数字是从0 ~ 15。需要注意的是,并不是所有数都是小数。从0 ~ 9都是基数为10的数字。一旦到了10,就需要改用字母来表示,10a(或A)、11b(或B)、12c(或C)、13d(或D),14e(或E),15f(或F)。即0 ~ 15的数字在十进制和十六进制对应的关系如下:

现在我们对十进制和十六进制数有了一个基础的了解。接着需要解决的是,十进制如何转换为十六进制(RGB#RRGGBB)或者十六进制如何转为十进制(#RRGGBBRGB)。我们先来看十进制转十六进制。

前面我们用视图层向大家演示了十进制数存储模型。除了用视图来表示之外,还可以用取余的计算模式来表示,比如42这个十进制数:

42 / 10 = 4 余 2
4 / 10  = 0 余 4

先用4210,得到商为4,余为2,接着用商4

剩余80%内容付费后可查看

如需转载,烦请注明出处:https://www.w3cplus.com/javascript/color-in-javascript.html

如果文章中有不对之处,烦请各位大神拍正。如果你觉得这篇文章对你有所帮助,打个赏,让我有更大的动力去创作。(^_^)。看完了?还不过瘾?点击向作者提问!

赏杯咖啡,鼓励他创作更多优质内容!
返回顶部