前端需要了解的色彩知識

前端 | 前端需要了解的色彩知識.png

前端需要了解的色彩知識

概述

在前端領(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)

color01.jpg

色環(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)烈

加色模式 & 減色模式

color02.png

在介紹加色模式和減色模式梢薪,我們先來看下我們從小學(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色模式的定義

加色模式是指對色彩模型中的屬性進(jìn)行加和的模式玻蝌;減色模式是指對色彩模型中的屬性進(jìn)行吸收的模式

那么為什么光學(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模型中咪笑,其就是典型的減色模式浸剩。

色彩模型

color03.png
color05.png

在有了對色彩的初步認(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

color_rgb.png

RGB模型是典型的加法模型,其通過設(shè)立RGB為三個(gè)基色進(jìn)行多種顏色的不同模型組合宿亡,其中R/G/B分別作為三維歐氏空間中的維度表示常遂,對顏色進(jìn)行相關(guān)的構(gòu)建,如上圖所示挽荠。

color_cmyk.gif

不同于RGB模型的加法合成克胳,對于印刷相關(guān)的場景,則是典型的減法合成圈匆,而這里最常見的就是跟物質(zhì)相關(guān)的基礎(chǔ)顏料作為基礎(chǔ)模型空間的維度漠另,最常見的便是CMYK模型,其仍然是符合歐氏空間的模型構(gòu)建跃赚,只是對于合成的算法過程中使用的是減法合成笆搓。

YUV & YCrCb

color_yuv.jpg

YUV模型作為RGB模型的變形形式,其常用于視頻纬傲、電視領(lǐng)域的色彩表示满败。由于在視頻及電視領(lǐng)域中,對于色調(diào)和飽和度的指標(biāo)相對更為關(guān)鍵叹括,因而使用U+V來表示色度葫录,使用Y來表示明亮度。

color_ycrcb.gif

隨著視頻編碼技術(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模型

color_hsl.png

對于HSL模型而言粱胜,最后定義的指標(biāo)是一個(gè)混入了黑白的量柄驻,其最后的形態(tài)在歐氏空間中,表現(xiàn)為一個(gè)全椎體焙压,如上圖所示鸿脓。

color_hsv.png

而對于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

color04.png

如上圖所示篱蝇,后續(xù)我們不加特別說明的話,后續(xù)將以HSV和HSL這兩種作為HS*的兩種典型代表進(jìn)行表述揪利,作為RGB模型的變種态兴,我們后續(xù)在色彩計(jì)算過程中對 HS* 和 RGB模型的換算進(jìn)行詳解。

LAB

color_lab.png

隨著發(fā)展疟位,人們對色彩的研究不再局限于設(shè)備基礎(chǔ)條件的限定瞻润,由此,CIE(Commission Internationale de Photométrie)國際照明協(xié)會提出了Lab模型甜刻,其不同于RGB的模型绍撞,其中L代表亮度,而a則是從深綠色(低亮)到灰色(中亮)再到亮粉紅色(高亮)的過渡得院,b則是亮藍(lán)色(低亮)到灰色(中亮)再到黃色(高亮)的過渡傻铣,其合成模型如上圖所示。

XYZ

color_xyz.png

在上一個(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色彩體系

色彩空間

color06.png

色彩空間又稱為色域帕识,在上一部分我們介紹了不同的色彩模型泛粹,那么對于實(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
color_antd.png
Ant Design色彩體系
Element Design
color_element.jpg
Element Design色彩體系
Material Design
color_material.png
Material Design色彩體系
Human Interface Guidelines
color_hig.png
Apple色彩體系
Fluent Design
color_fluent.png
微軟色彩體系

色彩計(jì)算

在理性的了解了色彩理論、色彩模型控硼、色彩空間以及感性的體會了色彩體系之后泽论,最后一部分我們來看一下之前所建立的理性與感性是如何通過計(jì)算進(jìn)行融合的,這一部分我將著重介紹和我們前端相關(guān)的色彩模型換算(RGB與HSV/HSL)卡乾,以及簡單介紹下在換算過程中可能涉及到的數(shù)學(xué)計(jì)算方法(貝塞爾曲線)翼悴,最后我們將通過ant design的色板實(shí)現(xiàn)來看一下色彩的具體應(yīng)用。

RGB/HSL/HSV換算

color09.png

在有了前邊關(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)換公式:

color_formula01.png

注意:R煞额、G、B都是換算到0-1區(qū)間的值沾谜,也就是這里的R/G/B是原本 0-255 區(qū)間的值除以255得到相應(yīng)的值

Hue的換算

color10.png

H的計(jì)算三者是一樣的膊毁,即:

color_formula02.png

Lightness/Value/Intensity的換算

color11.png

從上邊的換算過程可知,L基跑、V婚温、I的對應(yīng)方程為:

color_formula03.png

Saturation的換算

color12.png

對于飽和度的換算,由于L媳否、V栅螟、I的不同,導(dǎo)致?lián)Q算過程中的S也發(fā)生了變化:

color_formula04.png

貝塞爾曲線

color13.png

貝塞爾曲線作為數(shù)值計(jì)算中的重要方法篱竭,其對動態(tài)擬合不同運(yùn)動軌跡有十分重要的作用力图,作為插值計(jì)算來處理伯恩斯坦多項(xiàng)式的重要方法,其對于科學(xué)計(jì)算十分重要掺逼。

color14.gif

在對色彩計(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);
};
color15.png

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)融合,其中:

  1. 對于色相峰尝,在60到240度的色相進(jìn)行了色相的粒度分割偏窝;

  2. 對于飽和度,加深和減淡部分做了不同的粒度處理,其中減淡更快囚枪;

  3. 對于明度派诬,明度減弱也比加和粒度要更大;

不同于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昵簟!执赡!

參考

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末绊率,一起剝皮案震驚了整個(gè)濱河市谨敛,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌滤否,老刑警劉巖脸狸,帶你破解...
    沈念sama閱讀 207,248評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異藐俺,居然都是意外死亡炊甲,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評論 2 381
  • 文/潘曉璐 我一進(jìn)店門欲芹,熙熙樓的掌柜王于貴愁眉苦臉地迎上來卿啡,“玉大人,你說我怎么就攤上這事菱父【蹦龋” “怎么了?”我有些...
    開封第一講書人閱讀 153,443評論 0 344
  • 文/不壞的土叔 我叫張陵浙宜,是天一觀的道長揭鳞。 經(jīng)常有香客問我,道長梆奈,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,475評論 1 279
  • 正文 為了忘掉前任称开,我火速辦了婚禮亩钟,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘鳖轰。我一直安慰自己清酥,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,458評論 5 374
  • 文/花漫 我一把揭開白布蕴侣。 她就那樣靜靜地躺著焰轻,像睡著了一般。 火紅的嫁衣襯著肌膚如雪昆雀。 梳的紋絲不亂的頭發(fā)上辱志,一...
    開封第一講書人閱讀 49,185評論 1 284
  • 那天,我揣著相機(jī)與錄音狞膘,去河邊找鬼揩懒。 笑死,一個(gè)胖子當(dāng)著我的面吹牛挽封,可吹牛的內(nèi)容都是我干的已球。 我是一名探鬼主播,決...
    沈念sama閱讀 38,451評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼智亮!你這毒婦竟也來了忆某?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,112評論 0 261
  • 序言:老撾萬榮一對情侶失蹤阔蛉,失蹤者是張志新(化名)和其女友劉穎弃舒,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體馍忽,經(jīng)...
    沈念sama閱讀 43,609評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡棒坏,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,083評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了遭笋。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片坝冕。...
    茶點(diǎn)故事閱讀 38,163評論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖瓦呼,靈堂內(nèi)的尸體忽然破棺而出喂窟,到底是詐尸還是另有隱情,我是刑警寧澤央串,帶...
    沈念sama閱讀 33,803評論 4 323
  • 正文 年R本政府宣布磨澡,位于F島的核電站,受9級特大地震影響质和,放射性物質(zhì)發(fā)生泄漏稳摄。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,357評論 3 307
  • 文/蒙蒙 一饲宿、第九天 我趴在偏房一處隱蔽的房頂上張望厦酬。 院中可真熱鬧,春花似錦瘫想、人聲如沸仗阅。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽减噪。三九已至,卻和暖如春车吹,著一層夾襖步出監(jiān)牢的瞬間筹裕,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評論 1 261
  • 我被黑心中介騙來泰國打工窄驹, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留饶碘,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,636評論 2 355
  • 正文 我出身青樓馒吴,卻偏偏與公主長得像扎运,于是被迫代替她去往敵國和親瑟曲。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,925評論 2 344

推薦閱讀更多精彩內(nèi)容