1. 什麼是 EyeDropper
Chrome Devtools 的顏色提取器 EyeDropper,用慣了 Chrome 的前端開發者並不陌生。
但它並不支援在頁面中使用,想在頁面中使用只能自己實現一個。
那麼接下來就介紹一下如何自己實現一個 EyeDropper。
2. 原理解讀
要實現 EyeDropper,必須先學習一下基本的色彩知識。
物品被光線照射並反射出來,被人的眼睛接收,進而傳遞到人腦中形成對「色彩」的認知,稱之為人的「視覺效應」。
色彩的三屬性
1. 色相(hue)
最最基本的顏色術語、通常用來表示物體的顏色。
當我們說紅、綠、黃時,我們說的就是色相。將色相按照波譜順序排列,首位相連形成環狀則為「色相環」。雖然人們習慣將其分為七種顏色:紅、橙、黃、綠、青、藍、紫,但實際上的光譜應該是連續的。
2. 飽和度(saturation)
指在特定的光照條件下顏色是如何呈現的,也就是色彩的鮮豔程度。
飽和度取決於顏色中含色成分和消色成分(灰色)的比例,即純度最低的是灰色(無彩色)。高純度表現為生機朝氣,低純度表現為厚重沉穩。
3. 明度(value)
也被稱作亮度,它是指顏色的明亮程度。
在任何顏色中新增白色,明度上升,新增黑色,明度下降。明度相差越遠的兩種顏色搭配,色彩之間的交界感就越明顯,視覺上也就越清晰。
三者可以簡單用下圖綜合表示:
3. 方案設計
1. 模組梳理
理解了基礎的顏色原理後就好辦事了,拿 Chrome Devtools EyeDropper 分析:
- 飽和度和亮度選擇器。
- 色相選擇器。
- 透明度選擇器。
- 色彩轉換器。點選可以在 RGBA、HSL 和 HEX 之間切換。
- 調色盤。點選直接選擇不同的特定顏色。
- 取色器。在螢幕上直接選擇需要的顏色。
結合上述色彩知識,加上這塊分析就可以開始進入程式碼層面的設計。
2. 實際劃分
在元件化大行其道的時代,以網易慣用的 Regular 進行元件化開發。
根據模組劃分,劃分基礎的:
- 飽和度和亮度選擇元件;
- 色相選擇元件;
- 透明度選擇元件;
- 色彩輸入及轉換器元件。
考慮簡潔性,「取色器」及「調色盤」不做實現。
4. 元件實現
1. 色彩獲取功能實現
- 飽和度和亮度選擇元件(就是 EyeDropper 最上面那塊)
① 該元件以色相元件選擇的色相(hue)為背景,若是想直接使用 hue 作為 CSS 背景,需要使用 hsl(hue, saturation, value) 格式,設定為:
hsl(hue, 100%, 50%)複製程式碼
此時飽和度應設為 100%,因為飽和度為 0% 時為灰色,100% 時為原色。
而亮度是指顏色偏向於白色還是黑色。50%的亮度值表示顏色位於黑色和白色中間,這時顏色會基本保持原來的顏色不變。
② 同時利用線性漸變 linear-gradient
做色層疊加實現。
.saturation-white {
background: linear-gradient(to right, #fff, rgba(255,255,255,0));
}
.saturation-black {
background: linear-gradient(to top, #000, rgba(0,0,0,0));
}複製程式碼
- 色相元件(取顏色的那個條)
上面談到了色相環的概念,色相元件利用的就是色相環原理。
將 EyeDropper 中的色相條與色相環對比,是不是有異曲同工之妙?答對了,直接將圓環拍平即可。
獲取色值時只需要獲取當前位置對於最左端的百分比,換算成圓環角度。
Math.round(360 * percent / 100);複製程式碼
- 色彩輸入及轉換器元件
其中總共有 RGBA、HSL 和 HEX 三種格式的切換。
在 Regualr 中,內嵌元件的傳入屬性會掛在子元件的 data 上,並實現資料繫結。但考慮資料處理的統一性,在所有顏色的獲取處並不對顏色做處理,而是通過事件傳遞的方式,統一 $emit 到外層做統一的色值轉換。
this.$emit(`change`, {
h: hue,
s: saturation,
v: bright,
a: alpha
});
// 外層接收後統一處理
this.$on(`change`, processor);複製程式碼
接收到不同格式的顏色後,利用 tinycolor2 對顏色進行處理,使所有格式轉換為同一種顏色。
var color = tinycolor(colors);
var hsl = color.toHsl();
var hsv = color.toHsv();複製程式碼
2. 需要注意的問題
- 在使用滑鼠拖動選擇顏色時,需要做好節流處理,避免爆炸;
- 由於 JS 對於浮點數的奇妙控制,需要在輸入框做好統一截斷處理;
- 在滑鼠拖動的時間繫結及解綁中,注意繫結物件與解綁物件的一致性。
程式碼可以 戳我 檢視,具體實現如下: