EyeDropper 開發實踐

網易考拉前端團隊發表於2019-01-11

1. 什麼是 EyeDropper

Chrome Devtools 的顏色提取器 EyeDropper,用慣了 Chrome 的前端開發者並不陌生。

image
image

但它並不支援在頁面中使用,想在頁面中使用只能自己實現一個。

那麼接下來就介紹一下如何自己實現一個 EyeDropper。

2. 原理解讀

要實現 EyeDropper,必須先學習一下基本的色彩知識。

物品被光線照射並反射出來,被人的眼睛接收,進而傳遞到人腦中形成對「色彩」的認知,稱之為人的「視覺效應」。

色彩的三屬性

1. 色相(hue)

最最基本的顏色術語、通常用來表示物體的顏色。

當我們說紅、綠、黃時,我們說的就是色相。將色相按照波譜順序排列,首位相連形成環狀則為「色相環」。雖然人們習慣將其分為七種顏色:紅、橙、黃、綠、青、藍、紫,但實際上的光譜應該是連續的。

image
image

2. 飽和度(saturation)

指在特定的光照條件下顏色是如何呈現的,也就是色彩的鮮豔程度。

飽和度取決於顏色中含色成分和消色成分(灰色)的比例,即純度最低的是灰色(無彩色)。高純度表現為生機朝氣,低純度表現為厚重沉穩。

3. 明度(value)

也被稱作亮度,它是指顏色的明亮程度。

在任何顏色中新增白色,明度上升,新增黑色,明度下降。明度相差越遠的兩種顏色搭配,色彩之間的交界感就越明顯,視覺上也就越清晰。

三者可以簡單用下圖綜合表示:

image
image

3. 方案設計

1. 模組梳理

理解了基礎的顏色原理後就好辦事了,拿 Chrome Devtools EyeDropper 分析:

image
image

  1. 飽和度和亮度選擇器。
  2. 色相選擇器。
  3. 透明度選擇器。
  4. 色彩轉換器。點選可以在 RGBA、HSL 和 HEX 之間切換。
  5. 調色盤。點選直接選擇不同的特定顏色。
  6. 取色器。在螢幕上直接選擇需要的顏色。

結合上述色彩知識,加上這塊分析就可以開始進入程式碼層面的設計。

2. 實際劃分

在元件化大行其道的時代,以網易慣用的 Regular 進行元件化開發。

根據模組劃分,劃分基礎的:

  • 飽和度和亮度選擇元件;
  • 色相選擇元件;
  • 透明度選擇元件;
  • 色彩輸入及轉換器元件。

考慮簡潔性,「取色器」及「調色盤」不做實現。

4. 元件實現

1. 色彩獲取功能實現

  • 飽和度和亮度選擇元件(就是 EyeDropper 最上面那塊)

① 該元件以色相元件選擇的色相(hue)為背景,若是想直接使用 hue 作為 CSS 背景,需要使用 hsl(hue, saturation, value) 格式,設定為:

hsl(hue, 100%, 50%)複製程式碼

此時飽和度應設為 100%,因為飽和度為 0% 時為灰色,100% 時為原色。

image
image

而亮度是指顏色偏向於白色還是黑色。50%的亮度值表示顏色位於黑色和白色中間,這時顏色會基本保持原來的顏色不變。

image
image

② 同時利用線性漸變 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 對於浮點數的奇妙控制,需要在輸入框做好統一截斷處理;
  • 在滑鼠拖動的時間繫結及解綁中,注意繫結物件與解綁物件的一致性。

程式碼可以 戳我 檢視,具體實現如下:

image
image

附錄:

  1. EyeDropper 介紹

  2. Totally Tooling Tips with Addy Osmani & Matt Gaunt

相關文章