前端需要了解的色彩知識
概述
在前端領(lǐng)域,我們常常需要跟色彩打交道捎迫,除了一部分從設(shè)計(jì)轉(zhuǎn)過來的前端外(ps:歷史原因)酿秸,后來的新生代前端絕大多數(shù)基本都是學(xué)理工科出身的,一般沒有經(jīng)過專門的設(shè)計(jì)訓(xùn)練和培養(yǎng)头滔,這樣在還原設(shè)計(jì)圖的過程中對于色彩的理解都會或多或少有些出入,從而導(dǎo)致設(shè)計(jì)和前端產(chǎn)生不必要的矛盾(ps:本是同根生涎显,都相互體諒下)坤检,本文旨在通過介紹相關(guān)的一些色彩知識,為大家提供一些設(shè)計(jì)和前端雙重視角下的觀點(diǎn)期吓,也希望能夠給大家提供一些對色彩的不同的認(rèn)識和理解早歇。
色彩理論
人類對色彩的研究其實(shí)很早都有記錄,但真正把色彩作為一門學(xué)科或者說有其理論體系,還要從牛頓說起缺前,在之后不斷的科學(xué)發(fā)展過程中蛀醉,人們逐漸對色彩有了不同的認(rèn)識,也正是由于科學(xué)的發(fā)展衅码,色彩理論在不同領(lǐng)域都有了長足的發(fā)展拯刁,本文著重分享兩個(gè)對我們前端來說需要著重了解的色彩理論,即:色環(huán)理論以及加減色模式理論逝段。
色環(huán)
色環(huán)理論經(jīng)歷了牛頓色環(huán)垛玻、伊頓色環(huán)(傳統(tǒng)色環(huán))、孟塞爾色環(huán)奶躯、Yurmby色環(huán)等幾個(gè)不同的階段帚桩,這里重點(diǎn)介紹傳統(tǒng)的經(jīng)典色環(huán),也就是伊頓色環(huán)嘹黔,其作為包豪斯體系中重要的理論課程账嚎,對設(shè)計(jì)領(lǐng)域的影響巨大(ps:對設(shè)計(jì)史感興趣的童鞋,可以參看之前的這篇文章世界現(xiàn)代設(shè)計(jì)史)儡蔓,總體來說郭蕉,色環(huán)理論可以簡單提煉出以下幾個(gè)常見的色彩概念:
名稱 | 相差度數(shù) | 解釋 |
---|---|---|
鄰近色 | 0-15度 | 色環(huán)中兩色相差較小,比較接近喂江,不同人識別度不同召锈,通常識別度較低 |
相似色 | 15-45度 | 色環(huán)中兩色相差適中,既具有識別度获询,又具有相似度 |
中差色 | 45-105度 | 色環(huán)中兩色相差有明顯識別度涨岁,但又不會顯得過于跳躍 |
對比色 | 105-150度 | 色環(huán)中兩色相差有較強(qiáng)識別度,容易產(chǎn)生跳躍感 |
鄰近互補(bǔ)色 | 150-179度 | 色環(huán)中兩色相差較大吉嚣,不建議搭配使用 |
互補(bǔ)色 | 180度 | 色環(huán)中兩色相差對比強(qiáng)烈 |
加色模式 & 減色模式
在介紹加色模式和減色模式梢薪,我們先來看下我們從小學(xué)到的關(guān)于色彩的一些基本知識。我們之前上學(xué)的時(shí)候尝哆,美術(shù)老師可能教過三原色和三基色的概念沮尿,或者區(qū)分光學(xué)三原色和色彩三原色等等,這其實(shí)就已經(jīng)是加色模式和減色模式的一個(gè)初步了解了较解,本質(zhì)來說:三原色或者說三基色都是基于不同環(huán)境下材料而提出的一種基本色彩而已,我這里以光學(xué)三原色和色彩三原色來區(qū)分赴邻,光學(xué)三原色是:紅(R)印衔、綠(G)、藍(lán)(B)姥敛,也是我們前端開發(fā)過程中常用到的元色奸焙;而除了光學(xué)三原色外,還有一個(gè)色彩三原色,或者叫美術(shù)三原色与帆,它們是:紅(M)了赌、黃(Y)、藍(lán)(C)玄糟,這個(gè)是印刷或者繪畫過程中常常用到的元色勿她。相信細(xì)心的同學(xué)已經(jīng)發(fā)現(xiàn)我在標(biāo)注英語的時(shí)候,色彩三原色和光學(xué)三原色里的紅色及藍(lán)色好像是不一樣的阵翎,沒錯(cuò)逢并,正是由于不同場景下對于色彩使用的不同,而對色彩進(jìn)行加合的過程中出現(xiàn)了不同的模式郭卫。這里砍聊,就要引出我們這一部分的核心理論了,即:加色模式和減色模式贰军。
下面給出不嚴(yán)謹(jǐn)?shù)募由J胶蜏p色模式的定義
那么為什么光學(xué)色彩是加色法而美術(shù)色彩卻是減色呢?因?yàn)楸举|(zhì)上词疼,在光學(xué)場景中俯树,比如在計(jì)算機(jī)顯示器中通常使用的是從一種光源來發(fā)出不同的元色給人呈現(xiàn)色彩,不同的顯示器制造材料有不同的顯示特點(diǎn)寒跳,比如有:陰極射線管顯示器(CRT)聘萨、等離子顯示器(PDP)、液晶顯示器(LCD)以及有機(jī)發(fā)光半導(dǎo)體顯示器(OLED)等等童太,但這些通常都會是從一個(gè)光源發(fā)出的米辐,因而這些通常就是加色模型,而一般來說會有RGB模型书释、YUV(YCrCb)模型等翘贮,在前端來說,咱們常見的是以RGB模型進(jìn)行的相關(guān)對應(yīng)關(guān)系代碼操作爆惧,這里涉及到了色彩模型狸页,具體請看下一部分的介紹。而在美術(shù)或者印刷場景中扯再,則是利用的物體反射光線的原理芍耘,也就是說我們?nèi)粘?吹降奈矬w的顏色其實(shí)是顯示的它不能被吸收的顏色熄阻,例如:粉色顏料其實(shí)吸收了除粉色以外的所有光線荷科,所以我們才能看到它是粉色洁段,因而減色其實(shí)是吸收的模式煤搜,因而在CMYK模型中咪笑,其就是典型的減色模式浸剩。
色彩模型
在有了對色彩的初步認(rèn)識之后,如果想要來描述色彩鳄袍,我們就需要建立一個(gè)模型來描述它绢要,這里就引出了色彩模型的概念,基于wiki百科和百度百科拗小,我們不嚴(yán)謹(jǐn)?shù)慕o出如下的定義:
色彩模型是用一個(gè)元組或者集合來描述可見光的子集重罪,這里的元組通常為三元或者四元。
通常來說十籍,按照是否設(shè)備相關(guān)蛆封,我們可以將色彩模型分為設(shè)備相關(guān)色彩模型以及設(shè)備不相關(guān)的色彩模型,基于此大致可以分為兩大體系勾栗,即:RGB體系及XYZ體系惨篱,這里我們將介紹以下幾種常見的色彩模型:RGB/CMYK、YUV/YCrCb围俘、HS*砸讳、Lab、XYZ界牡,下面將分別介紹下相關(guān)的顏色模型簿寂。
RGB & CMYK
RGB模型是典型的加法模型,其通過設(shè)立RGB為三個(gè)基色進(jìn)行多種顏色的不同模型組合宿亡,其中R/G/B分別作為三維歐氏空間中的維度表示常遂,對顏色進(jìn)行相關(guān)的構(gòu)建,如上圖所示挽荠。
不同于RGB模型的加法合成克胳,對于印刷相關(guān)的場景,則是典型的減法合成圈匆,而這里最常見的就是跟物質(zhì)相關(guān)的基礎(chǔ)顏料作為基礎(chǔ)模型空間的維度漠另,最常見的便是CMYK模型,其仍然是符合歐氏空間的模型構(gòu)建跃赚,只是對于合成的算法過程中使用的是減法合成笆搓。
YUV & YCrCb
YUV模型作為RGB模型的變形形式,其常用于視頻纬傲、電視領(lǐng)域的色彩表示满败。由于在視頻及電視領(lǐng)域中,對于色調(diào)和飽和度的指標(biāo)相對更為關(guān)鍵叹括,因而使用U+V來表示色度葫录,使用Y來表示明亮度。
隨著視頻編碼技術(shù)的發(fā)展领猾,YCbCr模型作為視頻流采用的一種變形模型標(biāo)準(zhǔn)米同,其不再是通過u+v來表示色度,而是通過RGB輸入信號的R與亮度的差異即Cr和通過RGB輸入信號的B與亮度的差異即Cb進(jìn)行維度構(gòu)建摔竿,這相對于YUV或者YPrPb編碼而言便是數(shù)字色差信號而不再是模擬色彩信號了面粮。
YUV和YCrCb色彩模型常用于計(jì)算機(jī)視覺的相關(guān)分析中,對于視頻及圖像分析相關(guān)的同學(xué)可以更深入了解一下
HSV & HSL & HSB & HSI
對于人的視覺而言继低,其實(shí)通常最容易描述的就是基于色相(Hue)熬苍、飽和度(Saturation)以及最后這一個(gè)明度或者說亮度來區(qū)分,但是對于最后兩個(gè)指標(biāo)而言袁翁,不同模型的構(gòu)建其實(shí)是不太一樣的柴底,這里我們將重點(diǎn)介紹兩種模型,即:類HSL和類HSV模型
對于HSL模型而言粱胜,最后定義的指標(biāo)是一個(gè)混入了黑白的量柄驻,其最后的形態(tài)在歐氏空間中,表現(xiàn)為一個(gè)全椎體焙压,如上圖所示鸿脓。
而對于HSV模型而言,最后定義的指標(biāo)只是混入了一個(gè)黑色的量涯曲,其最后形態(tài)在歐氏空間中野哭,表現(xiàn)為一個(gè)倒立的圓錐體,如上圖所示幻件。
正是由于這種對于S和 *
的處理不同拨黔,導(dǎo)致出現(xiàn)了很多不同的名詞及表示模型,這里我們用以下表格做一下常見的 HS*
模型的對比:
簡寫 | 全稱 | 注釋 |
---|---|---|
HSV | Hue, Saturation, Value | 明度 |
HSL | Hue, Saturation, Lightness | 亮度 |
HSB | Hue, Saturation, Brightness | 明度 |
HSI | Hue, Saturation, Intensity | 亮度 |
結(jié)論:HSV = HSB绰沥,HSL ≈ HSI
如上圖所示篱蝇,后續(xù)我們不加特別說明的話,后續(xù)將以HSV和HSL這兩種作為HS*的兩種典型代表進(jìn)行表述揪利,作為RGB模型的變種态兴,我們后續(xù)在色彩計(jì)算過程中對 HS*
和 RGB模型的換算進(jìn)行詳解。
LAB
隨著發(fā)展疟位,人們對色彩的研究不再局限于設(shè)備基礎(chǔ)條件的限定瞻润,由此,CIE(Commission Internationale de Photométrie)國際照明協(xié)會提出了Lab模型甜刻,其不同于RGB的模型绍撞,其中L代表亮度,而a則是從深綠色(低亮)到灰色(中亮)再到亮粉紅色(高亮)的過渡得院,b則是亮藍(lán)色(低亮)到灰色(中亮)再到黃色(高亮)的過渡傻铣,其合成模型如上圖所示。
XYZ
在上一個(gè)Lab模型中我們知道祥绞,CIE對色彩做了進(jìn)一步的調(diào)研研究非洲,其實(shí)Lab模型也是XYZ模型的一個(gè)衍生變種鸭限,其對RGB模型中的光源做了坐標(biāo)系方面的區(qū)分,其對三元色進(jìn)行了相關(guān)的修正两踏,其是設(shè)備無關(guān)的败京,如上圖所示,在歐氏空間中梦染,兩個(gè)坐標(biāo)系發(fā)生了偏移赡麦。(ps:具體的變化,可以參考這篇文章RGB色彩體系和XYZ色彩體系)
色彩空間
色彩空間又稱為色域帕识,在上一部分我們介紹了不同的色彩模型泛粹,那么對于實(shí)際生產(chǎn)過程中會遇到各種不同的實(shí)際情況,因而各個(gè)廠家或者組織基于各自的設(shè)備或者場景的不同而實(shí)際形成的色彩映射關(guān)系肮疗,從而提出了各自的色彩范圍晶姊,這里我們結(jié)合wiki百科及百度百科,不嚴(yán)謹(jǐn)?shù)慕o出如下定義:
色彩空間是基于色彩模型而對實(shí)際特定場景的色彩范圍的映射關(guān)系族吻。
對于常見的色彩空間帽借,我們列舉了以下幾種:
色彩空間 | 色彩模型 | 注釋 |
---|---|---|
sRGB | RGB模型 | 微軟聯(lián)合HP、三菱等廠商開發(fā)的通用色彩標(biāo)準(zhǔn)超歌,通用的色彩標(biāo)準(zhǔn)砍艾,色彩范圍較小,也是網(wǎng)頁中常用的色彩空間標(biāo)準(zhǔn) |
adobe RGB | RGB模型 | Adobe主導(dǎo)開發(fā)巍举,盡可能使用計(jì)算機(jī)設(shè)備模擬印刷產(chǎn)品彩色樣式 |
ProPhoto RGB | RGB模型 | 柯達(dá)公司制定的色彩空間標(biāo)準(zhǔn)脆荷,常用于高端相機(jī) |
Japan Color 2001 Coated | CMYK模型 | 日本印刷業(yè)協(xié)會制定的一種色彩空間標(biāo)準(zhǔn) |
SWOP CMYK | CMYK模型 | 美國常用膠印墨色標(biāo)準(zhǔn)(US Web Coated),美國印刷業(yè)制定的一種色彩空間標(biāo)準(zhǔn) |
CIE 1931 XYZ | XYZ模型 | CIE 1931年制定的標(biāo)準(zhǔn) |
CIELAB | Lab模型 | 符合CIE 1931年的標(biāo)準(zhǔn)懊悯,從CIE LUV改進(jìn)而來 |
色彩體系
在講了關(guān)于色彩的一些基礎(chǔ)理論和描述之后蜓谋,我們來看一下設(shè)計(jì)領(lǐng)域?qū)τ谏实南嚓P(guān)運(yùn)用和實(shí)踐,這些對我們前端和設(shè)計(jì)同學(xué)協(xié)作也會有比較好的前置鋪墊炭分。
如果按照設(shè)計(jì)體系的標(biāo)準(zhǔn)制定桃焕,通常需要包含 愿景與原則(Vision & Principle)
、 指南(Guidelines)
捧毛、 庫與工具(Libraries & Tools)
這三層观堂,其中:
第一層:愿景與原則(Vision & Principle),是設(shè)計(jì)體系的核心價(jià)值觀及總體綱領(lǐng)呀忧,指引整體設(shè)計(jì)體系的風(fēng)格和調(diào)性师痕。
第二層:指南(Guidelines),包含樣式指南(Style Guideline)而账、模式指南(Patterns Guideline)胰坟、內(nèi)容指南(Content Guideline)等更多通過文字和圖像進(jìn)行傳達(dá)的內(nèi)容,也是大部分設(shè)計(jì)中對色彩(Color)泞辐、版式(Layout)笔横、竞滓。
第三層:庫與工具(Libraries & Tools),包含組件庫(Components Libraries)吹缔、工具包(Toolkits)虽界、協(xié)同工具(Collaborative Tools)等可以直接進(jìn)行使用的內(nèi)容,一般會輸出可開發(fā)使用的組件庫涛菠、以sketch或者psd的設(shè)計(jì)資源以及產(chǎn)品使用的figma、axure等物料撇吞。(ps:大型設(shè)計(jì)團(tuán)隊(duì)也會協(xié)同前端制作對應(yīng)的組件庫俗冻,比如常見的antd、element組件庫等都是對應(yīng)的設(shè)計(jì)團(tuán)隊(duì)的前端資源牍颈,一般來說大型的團(tuán)隊(duì)可能會將設(shè)計(jì)和前端劃入用戶體驗(yàn)團(tuán)隊(duì)迄薄,當(dāng)然這也需要看整體的組織架構(gòu))
之前做設(shè)計(jì)的時(shí)候,做過相關(guān)的設(shè)計(jì)體系煮岁,有興趣的同學(xué)讥蔽,可以看下這篇對應(yīng)的設(shè)計(jì)體系實(shí)踐——2018總結(jié)-多條業(yè)務(wù)線并行的UI基礎(chǔ)框架規(guī)范(附案例)
在剛才介紹了設(shè)計(jì)體系之后,我們看到對于第二層的guidelines中画机,對于樣式部分的規(guī)約冶伞,其中很重要的一個(gè)部分就是色彩,其實(shí)色彩是設(shè)計(jì)師展現(xiàn)視覺過程中最為重要的工具步氏,在包豪斯體系中响禽,作為三大構(gòu)成之一的色彩構(gòu)成是十分重要設(shè)計(jì)理論,而如果將色彩構(gòu)建成符合商業(yè)化的體系荚醒,通常來說需要包含兩大部分芋类,即:通用色彩系統(tǒng)和商業(yè)色彩系統(tǒng)。
對于色彩系統(tǒng)的分類界阁,這里我將以螞蟻金服的ant design色彩體系作為樣板來進(jìn)行描述侯繁。
通用色彩系統(tǒng),也就是antd中所說的系統(tǒng)級色彩體系泡躯,其是不包含任何關(guān)于商業(yè)及產(chǎn)品的特定色彩要求贮竟,只是設(shè)計(jì)師選出了幾種特定的色彩,配合不同的視覺感受來表達(dá)不同的傳達(dá)需求精续。
而商業(yè)色彩體系坝锰,也就是antd中所說的產(chǎn)品級色彩體系,通常需要配合品牌調(diào)性重付、產(chǎn)品功能等來從上述通用色彩系統(tǒng)中進(jìn)行著重的篩選和設(shè)定顷级,從而更好的服務(wù)商業(yè)化,用王受之先生的話講就是:“設(shè)計(jì)是對外的确垫,而藝術(shù)是對內(nèi)的”弓颈。
現(xiàn)階段的設(shè)計(jì)和工程結(jié)合的也越來越緊密帽芽,可以通過Design Token等手段將設(shè)計(jì)體系和工程體系進(jìn)行相關(guān)的對接,從而化解設(shè)計(jì)和前端鏈路過程中的溝通成本問題翔冀,提升工程效能导街。關(guān)于設(shè)計(jì)方面的鏈路方面的提升,可以看看螞蟻金服去年SEE Conf關(guān)于設(shè)計(jì)工程化的幾場介紹--提效神器 Design Tokens 的探索與應(yīng)用 - 昱星 & 元堯纤子、設(shè)計(jì)工程化三部曲 - 倏昱 & 聞冰
這里我列舉了幾個(gè)比較有名的設(shè)計(jì)團(tuán)隊(duì)所做的色彩體系風(fēng)格搬瑰,大家可以參考一下:
設(shè)計(jì)團(tuán)隊(duì) | 色彩體系 | 備注 |
---|---|---|
Ant Design | Ant Design色彩體系 | |
Element Design | Element Design色彩體系 | |
Material Design | Material Design色彩體系 | |
Human Interface Guidelines | Apple色彩體系 | |
Fluent Design | 微軟色彩體系 |
色彩計(jì)算
在理性的了解了色彩理論、色彩模型控硼、色彩空間以及感性的體會了色彩體系之后泽论,最后一部分我們來看一下之前所建立的理性與感性是如何通過計(jì)算進(jìn)行融合的,這一部分我將著重介紹和我們前端相關(guān)的色彩模型換算(RGB與HSV/HSL)卡乾,以及簡單介紹下在換算過程中可能涉及到的數(shù)學(xué)計(jì)算方法(貝塞爾曲線)翼悴,最后我們將通過ant design的色板實(shí)現(xiàn)來看一下色彩的具體應(yīng)用。
RGB/HSL/HSV換算
在有了前邊關(guān)于色彩模型的認(rèn)識后幔妨,我們來看一下色彩模型之間是如何進(jìn)行換算的鹦赎,由于前端應(yīng)用過程中主要涉及RGB向HS*的換算,因而這里我們僅僅介紹RGB模型是如何向HSL及HSV進(jìn)行坐標(biāo)體系換算的误堡。
從視頻中我們可以看出古话,RGB -> HSV
的過程為:
RGB傾斜 => 拉成六棱錐 => 轉(zhuǎn)成六棱柱 => 轉(zhuǎn)為圓柱
而 RGB -> HSL
的過程則為:
RGB傾斜 => 拉成雙六棱錐 => 轉(zhuǎn)成六棱柱 => 轉(zhuǎn)為圓柱
從這個(gè)過程,我們經(jīng)過一系列復(fù)雜的數(shù)學(xué)換算埂伦,可以得到如下轉(zhuǎn)換公式:
注意:R煞额、G、B都是換算到0-1區(qū)間的值沾谜,也就是這里的R/G/B是原本
0-255
區(qū)間的值除以255得到相應(yīng)的值
Hue的換算
H的計(jì)算三者是一樣的膊毁,即:
Lightness/Value/Intensity的換算
從上邊的換算過程可知,L基跑、V婚温、I的對應(yīng)方程為:
Saturation的換算
對于飽和度的換算,由于L媳否、V栅螟、I的不同,導(dǎo)致?lián)Q算過程中的S也發(fā)生了變化:
貝塞爾曲線
貝塞爾曲線作為數(shù)值計(jì)算中的重要方法篱竭,其對動態(tài)擬合不同運(yùn)動軌跡有十分重要的作用力图,作為插值計(jì)算來處理伯恩斯坦多項(xiàng)式的重要方法,其對于科學(xué)計(jì)算十分重要掺逼。
在對色彩計(jì)算過程中吃媒,使用貝塞爾曲線來處理兩個(gè)數(shù)據(jù)值也是一項(xiàng)十分重要的手段,可以更加接近對于色彩體系的構(gòu)建和對真實(shí)色彩世界的擬合。
Ant Design 色板
在介紹了所有的色彩相關(guān)的模型赘那、計(jì)算等等之后刑桑,我們來看一下前端中關(guān)于色彩計(jì)算的一些應(yīng)用,這里我們以螞蟻金服的 Ant Design 色板的生成算法作為案例進(jìn)行一些簡單的分析募舟,來看一下色彩計(jì)算在組件庫中的具體落地祠斧,對于更為詳細(xì)的介紹,大家可以看一下偏右大佬所寫的這篇《Ant Design 色板生成算法演進(jìn)之路》拱礁,這里我僅僅做一下個(gè)人的理解與分析簡述琢锋。
antd色板 1.x算法
// 變亮
@function tint($color, $percentage) {
@return mix(white, $color, $percentage);
}
// 變暗
@function shade($color, $percentage) {
@return mix(black, $color, $percentage);
}
// 使用
.useage {
background-color: tint(#2db7f5, 80%);
}
第一版的方法很簡單,我們看到直接使用了黑白的混合去處理呢灶,這里的mix是sass中的顏色混合方法吩蔑,這里使用的是簡單的RGB模型進(jìn)行換算,具體換算方法我找到了dart-sass的中的方法:
/// Returns [color1] and [color2], mixed together and weighted by [weight].
SassColor _mixColors(SassColor color1, SassColor color2, SassNumber weight) {
// This algorithm factors in both the user-provided weight (w) and the
// difference between the alpha values of the two colors (a) to decide how
// to perform the weighted average of the two RGB values.
//
// It works by first normalizing both parameters to be within [-1, 1], where
// 1 indicates "only use color1", -1 indicates "only use color2", and all
// values in between indicated a proportionately weighted average.
//
// Once we have the normalized variables w and a, we apply the formula
// (w + a)/(1 + w*a) to get the combined weight (in [-1, 1]) of color1. This
// formula has two especially nice properties:
//
// * When either w or a are -1 or 1, the combined weight is also that
// number (cases where w * a == -1 are undefined, and handled as a
// special case).
//
// * When a is 0, the combined weight is w, and vice versa.
//
// Finally, the weight of color1 is renormalized to be within [0, 1] and the
// weight of color2 is given by 1 minus the weight of color1.
var weightScale = weight.valueInRange(0, 100, "weight") / 100;
var normalizedWeight = weightScale * 2 - 1;
var alphaDistance = color1.alpha - color2.alpha;
var combinedWeight1 = normalizedWeight * alphaDistance == -1
? normalizedWeight
: (normalizedWeight + alphaDistance) /
(1 + normalizedWeight * alphaDistance);
var weight1 = (combinedWeight1 + 1) / 2;
var weight2 = 1 - weight1;
return SassColor.rgb(
fuzzyRound(color1.red * weight1 + color2.red * weight2),
fuzzyRound(color1.green * weight1 + color2.green * weight2),
fuzzyRound(color1.blue * weight1 + color2.blue * weight2),
color1.alpha * weightScale + color2.alpha * (1 - weightScale));
}
可以看到這里使用的是RGB模型的線性計(jì)算填抬,由于RGB模型線性換算過程中對間隔的變化十分巨大,對于人眼的視覺效果十分不友好
antd色板 2.x算法
@import "bezierEasing";
@import "tinyColor";
// We create a very complex algorithm which take the place of original tint/shade color system
// to make sure no one can understand it ??
// and create an entire color palette magicly by inputing just a single primary color.
// We are using bezier-curve easing function and some color manipulations like tint/shade/darken/spin
.colorPaletteMixin() {
@functions: ~`(function() {
var warmDark = 0.5; // warm color darken radio
var warmRotate = -26; // warm color rotate degree
var coldDark = 0.55; // cold color darken radio
var coldRotate = 10; // cold color rotate degree
var getShadeColor = function(c) {
var shadeColor = tinycolor(c);
// warm and cold color will darken in different radio, and rotate in different degree
// warmer color
if (shadeColor.toRgb().r > shadeColor.toRgb().b) {
return shadeColor.darken(shadeColor.toHsl().l * warmDark * 100).spin(warmRotate).toHexString();
}
// colder color
return shadeColor.darken(shadeColor.toHsl().l * coldDark * 100).spin(coldRotate).toHexString();
}
var primaryEasing = colorEasing(0.6);
this.colorPalette = function(color, index) {
var currentEasing = colorEasing(index * 0.1);
// return light colors after tint
if (index <= 6) {
return tinycolor.mix(
'#ffffff',
color,
currentEasing * 100 / primaryEasing
).toHexString();
}
return tinycolor.mix(
getShadeColor(color),
color,
(1 - (currentEasing - primaryEasing) / (1 - primaryEasing)) * 100
).toHexString();
};
})()`;
}
// It is hacky way to make this function will be compiled preferentially by less
// resolve error: `ReferenceError: colorPalette is not defined`
// https://github.com/ant-design/ant-motion/issues/44
.colorPaletteMixin();
在第二版的算法中隧期,使用的HSL模型進(jìn)行的整體色板粒度變化飒责,然后換算到RGB模型中。
其中在基于HSL模型分割粒度的時(shí)候仆潮,這里作者使用了自己定義的一個(gè)轉(zhuǎn)化方法宏蛉,對于灰度的判斷,使用的是r與b的比較性置,而這里的旋轉(zhuǎn)角度及darken比例個(gè)人以為應(yīng)該是作者根據(jù)實(shí)際生產(chǎn)數(shù)據(jù)獲得的經(jīng)驗(yàn)值拾并,這里我并沒有從相關(guān)資料中獲取到對應(yīng)的推到依據(jù)。
這里的RGB的混合也不再使用sass中的方法鹏浅,而是基于tinyColor中的混合方法嗅义,mix方法如下:
tinycolor.mix = function(color1, color2, amount) {
amount = (amount === 0) ? 0 : (amount || 50);
var rgb1 = tinycolor(color1).toRgb();
var rgb2 = tinycolor(color2).toRgb();
var p = amount / 100;
var rgba = {
r: ((rgb2.r - rgb1.r) * p) + rgb1.r,
g: ((rgb2.g - rgb1.g) * p) + rgb1.g,
b: ((rgb2.b - rgb1.b) * p) + rgb1.b,
a: ((rgb2.a - rgb1.a) * p) + rgb1.a
};
return tinycolor(rgba);
};
mix過程中的比例也不再是線性,而是使用的一個(gè)固定的貝塞爾曲線進(jìn)行繪制的曲線隐砸,從上圖中大體看出其基本符合線性的擬合之碗。
antd色板 3.x算法
前置算法,判斷亮度季希,使用了轉(zhuǎn)灰度的算法公式(ps:601校正公式褪那,由NTSC亮度方程推導(dǎo)而來),即:
Y = 0.299 * R + 0.587 * G + 0.114 * B
在tinycolor的庫中式塌,實(shí)現(xiàn)方式如下:
function getBrightness() {
//http://www.w3.org/TR/AERT#color-contrast
var rgb = this.toRgb();
return (rgb.r * 299 + rgb.g * 587 + rgb.b * 114) / 1000;
},
在下邊的 isLight
獲取就是從上述的 getBrightness
轉(zhuǎn)化而來
/* stylelint-disable no-duplicate-selectors */
@import "bezierEasing";
@import "tinyColor";
// We create a very complex algorithm which take the place of original tint/shade color system
// to make sure no one can understand it ??
// and create an entire color palette magicly by inputing just a single primary color.
// We are using bezier-curve easing function and some color manipulations like tint/shade/darken/spin
.colorPaletteMixin() {
@functions: ~`(function() {
var hueStep = 2;
var saturationStep = 0.16;
var saturationStep2 = 0.05;
var brightnessStep1 = 0.05;
var brightnessStep2 = 0.15;
var lightColorCount = 5;
var darkColorCount = 4;
var getHue = function(hsv, i, isLight) {
var hue;
if (hsv.h >= 60 && hsv.h <= 240) {
hue = isLight ? hsv.h - hueStep * i : hsv.h + hueStep * I;
} else {
hue = isLight ? hsv.h + hueStep * i : hsv.h - hueStep * I;
}
if (hue < 0) {
hue += 360;
} else if (hue >= 360) {
hue -= 360;
}
return Math.round(hue);
};
var getSaturation = function(hsv, i, isLight) {
var saturation;
if (isLight) {
saturation = hsv.s - saturationStep * I;
} else if (i === darkColorCount) {
saturation = hsv.s + saturationStep;
} else {
saturation = hsv.s + saturationStep2 * I;
}
if (saturation > 1) {
saturation = 1;
}
if (isLight && i === lightColorCount && saturation > 0.1) {
saturation = 0.1;
}
if (saturation < 0.06) {
saturation = 0.06;
}
return Number(saturation.toFixed(2));
};
var getValue = function(hsv, i, isLight) {
var value;
if (isLight) {
value = hsv.v + brightnessStep1 * I;
}else{
value = hsv.v - brightnessStep2 * I
}
if (value > 1) {
value = 1;
}
return Number(value.toFixed(2))
};
this.colorPalette = function(color, index) {
var isLight = index <= 6;
var hsv = tinycolor(color).toHsv();
var i = isLight ? lightColorCount + 1 - index : index - lightColorCount - 1;
return tinycolor({
h: getHue(hsv, i, isLight),
s: getSaturation(hsv, i, isLight),
v: getValue(hsv, i, isLight),
}).toHexString();
};
})()`;
}
// It is hacky way to make this function will be compiled preferentially by less
// resolve error: `ReferenceError: colorPalette is not defined`
// https://github.com/ant-design/ant-motion/issues/44
.colorPaletteMixin();
對于目前的antd 色板生成算法博敬,這里是基于HSV模型進(jìn)行的相關(guān)融合,其中:
對于色相峰尝,在60到240度的色相進(jìn)行了色相的粒度分割偏窝;
對于飽和度,加深和減淡部分做了不同的粒度處理,其中減淡更快囚枪;
對于明度派诬,明度減弱也比加和粒度要更大;
不同于2.x使用的貝塞爾曲線去擬合曲線链沼,這里又改回線性組合來進(jìn)行符合色彩體系的可控調(diào)整默赂,從而使得整體的方案特別清晰明了,但又不同于1.x中的暴力組合括勺,這里的灰度推算是基于亮度方程來作為科學(xué)依據(jù)的換算缆八,算是融合了1.x和2.x各自的特點(diǎn)
總結(jié)
在前端開發(fā)過程中,我們在幫助設(shè)計(jì)師對于色彩體系的構(gòu)建時(shí)疾捍,除了對于日常常見的一些感知層面的理解外奈辰,我們更應(yīng)該注重對于深層原理的探索與探究,追問科學(xué)深層的認(rèn)知乱豆,對于我們探索前端領(lǐng)域的深層有著至關(guān)重要的作用奖恰,比如在色彩中的計(jì)算機(jī)視覺方面的探索,讓我們對于工程與設(shè)計(jì)鏈路的擴(kuò)展提供了更高層次和維度的認(rèn)識宛裕,希望各位同學(xué)在后續(xù)研發(fā)過程中瑟啃,都能通過探索底層追問,獲取到對于自己工作邊界的認(rèn)知探索揩尸。
色彩的研究絕不僅僅涉及到色彩理論蛹屿、色彩模型、色彩空間岩榆、色彩計(jì)算等错负,其實(shí)色彩是一門十分有意思且可以很深入的學(xué)科,對于我們前端來講則更為重要勇边,作為連接設(shè)計(jì)與數(shù)據(jù)的紐帶犹撒,也作為關(guān)聯(lián)用戶與企業(yè)的先鋒,我們對前端理論學(xué)習(xí)的同時(shí)也要對相關(guān)科學(xué)理論知識作補(bǔ)充粒褒,做到能夠?qū)χR的靈活運(yùn)用油航,幫助企業(yè)和用戶提升更好的體驗(yàn),這也是我們作為前端工程師的更高價(jià)值所在怀浆,共勉R昵簟!执赡!
參考
- 圖像特效及濾鏡算法匯總
- Ant Design 色板生成算法演進(jìn)之路
- HSL and HSV
- 貝塞爾曲線掃盲
- Color code converter
- 前端也要懂的一些色彩知識
- 前端需要了解的顏色模型镰踏,RGB、HSL和HSV
- 如何快速實(shí)現(xiàn)一個(gè)顏色選擇器
- RGB和HSB色彩模型和算法
- 系統(tǒng)級和產(chǎn)品級色彩體系
- antd中的調(diào)色版計(jì)算方法
- COLOR SYSTEMS
- 色彩模型與色彩空間
- 【攝影教程】色彩基礎(chǔ)(三):攝影常用的色彩空間
- 什么是YUV
- YUV簡介
- 加色法與減色法
- 設(shè)計(jì)體系:數(shù)字產(chǎn)品設(shè)計(jì)的系統(tǒng)化方法
- 設(shè)計(jì)體系(一)丨設(shè)計(jì)體系的涌現(xiàn):適應(yīng)組織的需要
- 設(shè)計(jì)體系(二)丨什么才是設(shè)計(jì)體系沙合?結(jié)構(gòu)奠伪、原則與認(rèn)知誤區(qū)
- 設(shè)計(jì)體系(三)丨設(shè)計(jì)體系有什么用?價(jià)值與缺陷
- 設(shè)計(jì)體系(四)丨如何創(chuàng)建設(shè)計(jì)體系?
- Naming Tokens in Design Systems
- Design Token 應(yīng)用指南——設(shè)計(jì)篇
- Tint and Shade Functions
- Bézier基函數(shù)的導(dǎo)出
- 拒絕被忽悠 手機(jī)屏幕材質(zhì)/技術(shù)淺解析