者 | Adam Giese
译者 | 王强
CSS 中有两种颜色模型 RGB 和 HSL,如何用 JavaScript 控制它们?
点开这篇文章的你,肯定是想要学习怎样控制颜色的——我们后面就会讲具体操作。但首先,我们需要对 CSS 如何标记颜色有一个基本的认识。CSS 使用的是两种颜色模型:RGB 和 HSL,我们先简单了解一下。
1、RGB
RGB 就是“红色,绿色,蓝色”的简称。这个模型由三个数字组成,每个数字表示其所代表的颜色在最终生成的颜色中有多高的亮度。在 CSS 中,每个数值的范围都是 0-255,三个数值间用逗号分隔,作为 CSS rgb 函数的参数,例如:rgb(50,100,0)。
RGB 是一种“增量”颜色系统。这意味着每个数字越高,最终生成的颜色就越亮。如果所有值都相等就生成灰度颜色;如果所有值都为零,结果为黑色;如果所有值都是 255,则结果为白色。
此外你也可以使用十六进制表示法来标记 RGB 颜色,其中每种颜色的数值从 10 进制转换为 16 进制。例如,rgb(50,100,0)用 16 进制就写成#326400。
虽然我个人比较习惯使用 RGB 模型(特别是十六进制),但我也经常发现它不易阅读,也不容易操作。下面来看 HSL 模型。
2、HSL
HSL(https://codepen.io/AdamGiese/full/989988044f3b8cf6403e3c60f56dd612)是“色调,饱和度,光线”的简称,HSL 也包含三个值。色调值对应于色轮上的点,由 CSS 角度值表示,最常用的是度数单位。
饱和度以百分比表示,是指颜色的强度。当饱和度为 100%时颜色最深,饱和度越低,颜色越浅,直到灰度为 0%。
亮度也以百分比表示,指的是颜色有多亮。“常规”的亮度是 50%。无论色调和饱和度值如何,100%的亮度都是纯白色,0%的亮度就是纯黑色。
我觉得 HSL 模型更直观一些,颜色之间的关系更加明显,控制颜色时只要简单地调整几个数字就可以了。
3、颜色模型之间的转换
RGB 和 HSL 颜色模型都将颜色分解为各种属性。要在不同模型之间进行转换,我们首先需要计算这些属性。
除了色调,上面提到的所有数值都可以表示为百分比。就连 RGB 值也是用字节表示的百分比。在下面提到的公式和函数中,这些百分比将由 0 到 1 之间的小数来表示。
这里提一下,我并不会深入探讨这些数学知识;相比之下,我将简要介绍一遍原始数学公式,然后将其转换为 JavaScript 格式。
4、从 RGB 模型中计算亮度
亮度是三个 HSL 值中最容易计算的一个。其数学式如下,其中 M 是 RGB 值的最大值,m 是最小值:
亮度的数学式
用 JavaScript 函数写成下面的形式:
const rgbToLightness =(r,g,b)=> 1/2 *(Math.max(r,g,b)+ Math.min(r,g,b));
5、从 RGB 模型中计算饱和度
饱和度仅比亮度稍微复杂一些。如果亮度为 0 或 1,则饱和度值为 0;否则,它基于下面的数学公式计算得出,其中 L 表示亮度:
饱和度的数学式
写成 JavaScript:
const rgbToSaturation = (r,g,b) => { const L = rgbToLightness(r,g,b); const max = Math.max(r,g,b); const min = Math.min(r,g,b); return (L === 0 || L === 1) ? 0 : (max - min)/(1 - Math.abs(2 * L - 1)); };
6、从 RGB 模型中计算色调
从 RGB 坐标中计算色调角度的公式有点复杂:
色调的数学式
写成 JavaScript:
const rgbToHue = (r,g,b) => Math.round( Math.atan2( Math.sqrt(3) * (g - b), 2 * r - g - b, ) * 180 / Math.PI );
最后 180 / Math.PI 的算法是将结果从弧度转换为度。
7、计算 HSL
上面这些函数都可以包含在同一个功能函数里:
const rgbToHsl = (r,g,b) => { const lightness = rgbToLightness(r,g,b); const saturation = rgbToSaturation(r,g,b); const hue = rgbToHue(r,g,b); return [hue, saturation, lightness]; }
8、从 HSL 模型中计算 RGB 值
开始计算 RGB 之前,我们需要一些前提值。
首先是“色度”值:
色度的数学式
还有一个临时的色调值,我们将用它来确定我们所属的色调圈的“段”:
色调区间的数学式
接下来,我们设一个“x”值,它将用作中间(第二大)组件值:
临时“x”值的数学式
我们再设一个“m”值,用于调整各个亮度值:
亮度匹配的数学式
根据色调区间值,r,g 和 b 值将映射到 C,X 和 0:
RGB 值的数学式,不考虑亮度
最后,我们需要映射每个值以调整亮度:
用 RGB 来解释亮度的数学式
将上面这些都写到 JavaScript 函数中:
const hslToRgb = (h,s,l) => { const C = (1 - Math.abs(2 * l - 1)) * s; const hPrime = h / 60; const X = C * (1 - Math.abs(hPrime % 2 - 1)); const m = l - C/2; const withLight = (r,g,b) => [r+m, g+m, b+m]; if (hPrime <= 1) { return withLight(C,X,0); } else if (hPrime <= 2) { return withLight(X,C,0); } else if (hPrime <= 3) { return withLight(0,C,X); } else if (hPrime <= 4) { return withLight(0,X,C); } else if (hPrime <= 5) { return withLight(X,0,C); } else if (hPrime <= 6) { return withLight(C,0,X); } }
9、创建颜色对象
为了便于在操作属性时访问,我们将创建一个 JavaScript 对象。把前面提到的这些函数打包起来就能创建这个对象:
const rgbToObject = (red,green,blue) => { const [hue, saturation, lightness] = rgbToHsl(red, green, blue); return {red, green, blue, hue, saturation, lightness}; } const hslToObject = (hue, saturation, lightness) => { const [red, green, blue] = hslToRgb(hue, saturation, lightness); return {red, green, blue, hue, saturation, lightness}; }
10、示例
我强烈建议你花些时间看看这个示例:
https://codepen.io/AdamGiese/full/86b353c35a8bfe0868a8b48683faf668
从中了解调节各个属性时其它属性如何发生变化,这样能帮助你更深入地了解两种颜色模型是如何对应的。
现在我们已经知道怎样在颜色模型之间进行转换了,那么就来看看该如何控制这些颜色!
1、更新属性
我们提到的所有颜色属性都可以单独控制,返回一个新的颜色对象。例如,我们可以编写一个旋转色调角度的函数:
const rotateHue = rotation => ({hue, ...rest}) => { const modulo = (x, n) => (x % n + n) % n; const newHue = modulo(hue + rotation, 360); return { ...rest, hue: newHue }; }
rotateHue 函数会接受一个旋转参数并返回一个新函数,该函数接受并返回一个颜色对象。这样就可以轻松创建新的“旋转”函数:
const rotate30 = rotateHue(30); const getComplementary = rotateHue(180); const getTriadic = color => { const first = rotateHue(120); const second = rotateHue(-120); return [first(color), second(color)]; }
用这种方式,你也可以编写加深或提亮颜色的函数——或者反过来,减淡或变暗也行。
const saturate = x => ({saturation, ...rest}) => ({ ...rest, saturation: Math.min(1, saturation + x), }); const desaturate = x => ({saturation, ...rest}) => ({ ...rest, saturation: Math.max(0, saturation - x), }); const lighten = x => ({lightness, ...rest}) => ({ ...rest, lightness: Math.min(1, lightness + x) }); const darken = x => ({lightness, ...rest}) => ({ ...rest, lightness: Math.max(0, lightness - x) });
2、颜色谓词
除了颜色控制以外,你还可以编写“谓词”——亦即返回布尔值的函数。
const isGrayscale = ({saturation}) => saturation === 0; const isDark = ({lightness}) => lightness < .5;
3、处理颜色数组
过滤器
JavaScript [] .filter 方法会接受一个谓词并返回一个新数组,其中包含所有“传递”的元素。我们在上一节中编写的谓词可以用在这里:
const colors = [/* ... an array of color objects ... */]; const isLight = ({lightness}) => lightness > .5; const lightColors = colors.filter(isLight);
排序
要对颜色数组进行排序,首先需要编写一个“比较器”函数。此函数接受一个数组的两个元素并返回一个数字来表示“赢家”。正数表示第一个元素应该先排序,而负数表示第二个元素应该先排序。零值表示平局。
例如,这是一个比较两种颜色亮度的函数:
const compareLightness = (a,b) => a.lightness - b.lightness;
这是一个比较饱和度的函数:
const compareSaturation = (a,b) => a.saturation - b.saturation;
为了防止代码重复,我们可以编写一个高阶函数来返回一个比较函数来对比各种属性:
const compareAttribute = attribute => (a,b) => a[attribute] - b[attribute]; const compareLightness = compareAttribute('lightness'); const compareSaturation = compareAttribute('saturation'); const compareHue = compareAttribute('hue');
平均属性
你可以搭配各种 JavaScript 数组方法来平衡颜色数组中的特定属性。首先,你可以使用 reduce 求和并用 Array length 属性分割来计算一个属性的均值:
const colors = [/* ... an array of color objects ... */]; const toSum = (a,b) => a + b; const toAttribute = attribute => element => element[attribute]; const averageOfAttribute = attribute => array => array.map(toAttribute(attribute)).reduce(toSum) / array.length;
你可以用它来“规范化”一组颜色:
/* ... continuing */ const normalizeAttribute = attribute => array => { const averageValue = averageOfAttribute(attribute)(array); const normalize = overwriteAttribute(attribute)(averageValue); return normalize(array); } const normalizeSaturation = normalizeAttribute('saturation'); const normalizeLightness = normalizeAttribute('lightness'); const normalizeHue = normalizeAttribute('hue');
4、结论
颜色是网络不可或缺的一部分。将颜色分解为属性就可以灵活控制它们,并创造出无限的可能。
查看英文原文:
https://blog.logrocket.com/how-to-manipulate-css-colors-with-javascript-fb547113a1b8
福利推荐
前端领域的技术演进一直要比其他技术快一些,这给前端工程师带来持续的挑战。这里整理了从 Vue 到 React、iOS 到 Andoid、再到前端架构体系的干货课程,带你解读从前端小工到专家的实战心法,高效解决 80% 的开发难题。
tml代码里,表示颜色一般用两种方法,一种是直接写出颜色的英文,另一种是前面写个“#”后面再写6个数字字母。
先说第一种表示方法,这个很简单,如果要表示黑色直接就是black,红色就red,蓝色就blue。具体的我们看下面图1,图2
图1
图2
现在来说第二种,这也是我们这个文章要重点说的,因为这个也是最经常用的表示方法,很多人看到这个又是字数又是字母的就糊涂了,今天我们来详细的把它讲清楚。先用图片来说明一下,先看下面图3
图3
图3里的#000000表示的是黑色,#ff0000表示红色,#00ff00表示绿色,所以说这个效果是和图1一样的。那要怎么理解这种表示颜色的方法呢,我们再来列出几个颜色和它的表示法:
红色:#ff0000,绿色:#00ff00,蓝色:#0000ff, 大家仔细看一下就可发现,这个和我们平常说的RGB格式来表示颜色是一样的,相当于红绿蓝三个光,而f是十六进制中的0,1,2,.....e,f中的f了 。f是里面的最大值了,ff代表该颜色光的值达到最大,所以#ff0000是红色,#880000表示的也是红色,只是没有#ff0000这个那么红了。其他的也是同理。所以#000000代表三个颜色光的值都为0,没有任何光了,那就是黑色了,相反#ffffff代表三个颜色光的值都达到最大,混合在一起就成白色。我们也知道红光和蓝光混在一起是紫色的,所以#ff00ff表示的是紫色,同样#ffff00表示的是黄色。讲到这里相信大家应该都明白了怎样用这种方法表示颜色了吧,如果要表示一种颜色,只要把相应的值增加或减小或者添加另一个颜色,这样就可以得到千千万万种颜色了。
这两种表示颜色的方法都讲完了,尤其是第二种方法,大部分情况都是用这种方法来表示html里面的颜色的。如果大家有什么更好的更容易理解的想法,可以点击关注【点点有你】一起来讨论一下哦
最后,如果您觉得我写的这些文章对您有帮助的话,您可以根据您的情况随意给点赏金,我相信一分也是爱也是支持,下面两图是我的支付宝和微信收款码。当然写文章不是一定要让您给赏金的,有您的支持和赞助,我会有更多动力来写文章和大家分享的,再次感谢您的支持和理解!
官网是这样介绍的:使用我们的颜色选择器、颜色表和HTML颜色名称来获取HTML颜色代码、Hex颜色代码、RGB和HSL值。即刻开始吧!
寻找完美色彩从未如此简单,使用我们的HTML颜色选择器来浏览上百万的颜色和色彩搭配。
颜色选择器
颜色选择器动图
操作:
选取颜色
点击左侧颜色样本将其添加到您的调色板。
保存颜色
在您的调色板上保存和撤销保存颜色;下次您访问时候它们会在这里。
导出颜色
将您当前的调色板以Hex、RGB、HTML、CSS和SCSS 格式输出。试一下吧!
有了这些扁平化设计、Material Design和网页安全颜色表,一定可以为您的网页或应用程序找到完美的色彩方案 – 只需不停地寻找!
颜色表
颜色表动图
现代浏览器支持140种已命名的颜色,如下所列。根据名称、Hex代码或RGB值将其用于您的HTML和CSS。
颜色名
如何使用HTML颜色名
之所以建立HTML颜色代码,是因为我们认为设计工具本身有应有精良的设计。如果您喜欢这个网站或有何建议与反馈,欢迎您随时发电子邮件与我们联系
同时这个网站还有其他有趣好玩的分享,比如最佳调色板生成器(选择完美的色彩方案是任何网站或项目的关键部分,为了帮助您找寻完美的颜色组合,我们已将今天最佳的调色板生成器和网络工具收集在一起编成列表),终极指南免费库存照片(每个网站都需要很好的创造力,所以我们将最喜爱的可获得免版税图库照片的地方汇集做成特赞的列表。没错,全部是魅力图库图片,100%免费),如何根据颜色搜索图片(搜索与您的颜色方案相匹配的图片可能会相当耗时,所以我们把最爱的图片搜索工具列成了一个简短的清单,这些工具可以使用颜色对其搜索结果加以过滤或完善)等等
最后说一遍,这个网站有中文,有中文,有中文
网址分享,打开馨客栈导航:http://www.mackxin.com/nav.html
然后找到下图所示:
在线HTML颜色代码
更多分享,请关注馨客栈
关注分享,体验乐趣
*请认真填写需求信息,我们会在24小时内与您取得联系。