整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          用JavaScript的Brain.js訓練人工智能

          用JavaScript的Brain.js訓練人工智能神經網絡來識別手寫數字

          ntroduction 介紹

          人工智能和機器學習是軟件開發的一個令人興奮的新前沿。雖然新的工具,網站和其他資源不斷涌現,但其中大多數都是用Python(或者R)編寫的。如果你是一個前端開發人員(他最喜歡的語言可能是JavaScript),你可能會想知道你是否有可能探索這個新世界。

          幸運的是,這個問題的答案是肯定的。有一些庫可以讓你在不了解Python一行的情況下練習機器學習。在本教程中,我們將探討其中之一 - 大腦.js - 并展示如何構建,訓練和使用只有JavaScript的深度神經網絡(DNN)。

          Learning objectives 學習目標

          我們將逐步完成一個預構建的 DNN。我們將展示它如何從 UI 中工作,深入研究將 UI 連接到 DNN 的代碼,然后解釋實際創建和訓練 DNN 的代碼。然后,我們將回過頭來解釋 DNN 是什么、它們如何工作以及人們如何創建和改進它們的一些基本概念。在此過程中,我們將發現DNN如何使我們能夠以令人驚訝的少代碼獲得令人印象深刻的結果。

          Prerequisites 前置條件準備

          本文假定您之前沒有 DNN 或機器學習方面的經驗

          For the tutorial, you will need:

          • Basic familiarity with JavaScript 對腳本的基本熟悉程度
          • Basic familiarity with Git and GitHub 對 Git 和 GitHub 的基本熟悉程度


          步驟1. Draw and predict

          克隆存儲庫后,在所選瀏覽器中打開數字計算器.html文件。加載時,您應該會看到以下內容。


          這是數字預測應用程序的 UI,該應用程序使用 DNN 來猜測您在其網格中繪制的內容。

          嘗試在網格中繪制一個數字;它可以是 0 到 9 之間的任何值(僅限一位數字)。您可以通過單擊網格中的正方形,按住鼠標左鍵并拖動它來繪制數字,完成后釋放。

          繪制完某些內容后,單擊“獲取評估”按鈕。這樣做應該會產生如圖 2 所示的反饋。

          若要進行其他預測,請單擊“清除輸入”按鈕并在網格中繪制另一個數字,然后再次單擊“獲取評估”。

          Here's what just happened 這是剛剛發生的事情

          希望到現在為止,您已經對此程序的工作原理很感興趣。到目前為止,您已經與預先訓練的 DNN 進行了交互。

          在非常基本的層面上,您正在創建輸入 - 您繪制的數字 - 并將其饋送到DNN。反過來,DNN正在使用它以前教授的內容(稍后會詳細介紹)來進行有根據的猜測或預測。代碼在 UI 中顯示此預測,并添加了一些詳細信息,例如黃色突出顯示,以使網絡的選擇更加明顯。

          步驟2. 使用Brain.js 庫構建DNN訓練

          我們現在將演練代碼,以便您可以看到使用大腦.js庫在JavaScript中實現DNN是什么樣的。完成此操作后,我們將退后一步,更廣泛地討論 DNN 的工作原理,并回顧我們看到的代碼,以將其全部聯系在一起。

          當我們單擊“獲取評估”按鈕時,我們可以看到它調用了一個名為getAssessment():

          <button onclick="getAssessment()" style="width:49%;">
              Get Assessment
          </button>

          當我們在數字計算器.html文件中向下滾動時,我們可以看到 getAssessment() 的定義:

          function getAssessment() {
              const inputArray=captureAndTransformInput()
              let ourNetwork=ourNeuralNetwork
              const result=arrayToHTML(resultToArray(ourNetwork.run(inputArray)))
          
              document.getElementById('assessment').innerHTML=result
          }

          getAssessment() 函數是我們創建的,因此我們的 UI 可以與大腦.js庫創建的 DNN 對象進行通信(稍后會詳細介紹)。

          如果要使用 DNN,我們需要做的第一件事就是獲取有關我們在屏幕上繪制的內容的數據。我們需要給 DNN 一些要檢查的東西。我們使用為演示創建的另一個函數來執行此操作,該函數稱為捕獲和轉換輸入()。此函數循環訪問我們網頁上的網格,并檢查哪些框被涂成紅色,哪些框沒有。然后,它采用所有這些數組,并將整體轉換為 1 和 0 的數組,并返回結果:

          function captureAndTransformInput() {
              const boxes=Array.from(document.getElementsByClassName('cell'))
              const toOnesOrZeros=box=> box.style.backgroundColor==='red' ? 1 : 0
              return boxes.map(toOnesOrZeros)
          }

          我們需要執行此轉換,因為 Brain.js 庫提供給我們的 DNN 將不知道如何處理原始數據(來自 HTML 頁面的顏色信息)。我們的 DNN 只知道如何處理 1 和 0 的列表。

          使用深度學習術語,我們正在使用捕獲和轉換輸入函數為我們的 DNN 創建一個輸入向量。

          步驟 3. 使用DNN 來判斷準確度

          所有 DNN 都需要一個輸入向量來完成其工作。即使是你可能聽說過的神經網絡示例,例如那些處理照片以確定它們是否包含貓或狗的示例,也不能直接處理照片。

          相反,腳本(通常是Python)從照片中獲取像素信息并將其解卷成一長串值,這些值通常是表示照片中每個像素的每個RGB值的不同部分的數字。結果稱為輸入向量,對于照片,它可以包含許多值。我們正在對捕獲和轉換輸入()執行類似的操作,盡管更簡單。

          現在我們有了輸入向量,我們可以使用 DNN 對剛剛繪制的內容進行分類,并確定其準確性。

          使用 Brain.js庫時,將創建一個包含有關 DNN 的信息的對象。此對象的一個方面是名為 run() 的方法。這就是實際生成的預測,最終在我們看到的網頁上結束:

          ourNeuralNetwork.run(...)

          但在我們實際使用我們的 DNN 對象之前,我們必須先訓練它并設置一些參數。我們很快就會解釋這一點,但現在我們將繼續看到網絡的預測如何將其返回到網頁。

          brain.js run() 方法將輸入向量作為參數并返回結果。此結果是一個 JSON 有效負載,其中包含有關 DNN 對我們繪制的數字的有根據的猜測的信息。在我們的教程中,我們將captureAndTransformInput()函數的輸出提供給run()方法:

          const inputArray=captureAndTransformInput()
          const result=arrayToHTML(resultToArray(ourNeuralNetwork.run(inputArray)))
          The output of the run() method - i.e., our network’s prediction - is then passed to another “transformer” function we have created called resultToArray():
          
          function resultToArray(resultToConvert) {
              let arrayToReturn=[]
          
              arrayToReturn.push({ label: 'Zero', likelihood: resultToConvert.Zero, topChoice: 0, ordinal: 0 })
              arrayToReturn.push({ label: 'One', likelihood: resultToConvert.One, topChoice: 0, ordinal: 1 })
              arrayToReturn.push({ label: 'Two', likelihood: resultToConvert.Two, topChoice: 0, ordinal: 2 })
              arrayToReturn.push({ label: 'Three', likelihood: resultToConvert.Three, topChoice: 0, ordinal: 3 })
              arrayToReturn.push({ label: 'Four', likelihood: resultToConvert.Four, topChoice: 0, ordinal: 4 })
              arrayToReturn.push({ label: 'Five', likelihood: resultToConvert.Five, topChoice: 0, ordinal: 5 })
              arrayToReturn.push({ label: 'Six', likelihood: resultToConvert.Six, topChoice: 0, ordinal: 6 })
              arrayToReturn.push({ label: 'Seven', likelihood: resultToConvert.Seven, topChoice: 0, ordinal: 7 })
              arrayToReturn.push({ label: 'Eight', likelihood: resultToConvert.Eight, topChoice: 0, ordinal: 8 })
              arrayToReturn.push({ label: 'Nine', likelihood: resultToConvert.Nine, topChoice: 0, ordinal: 9 })
          
              const byLikelihood=(x, y)=> x.likelihood < y.likelihood ? 1 : -1
              const byOrdinal=(x, y)=> x.ordinal < y.ordinal ? -1 : 1
          
              const topChoiceDesignation=(e, i, a)=> {
                  e.topChoice=i===0 ? 1 : 0  // mark the first entry (index 0) as the top choice - we can do this because we've already sorted them to ensure that the top choice is the first item 
                  return e
              }
          
              return arrayToReturn.sort(byLikelihood)
                  .map(topChoiceDesignation)
                  .sort(byOrdinal)
          }

          此函數接收預測數據(結果到轉換)并創建一個新數組(數組 ToReturn),其中包含可用于在 UI 中顯示結果的信息。我們的 DNN 返回的輸出將是一個具有 10 個屬性(零、一、二、三、四、五、六、七、八、九)的對象,每個屬性都有映射到它的概率(介于 0 和 1 之間)。

          因此,例如,來自 DNN(結果到轉換參數)的預測有效負載可能如下所示(我們的 DNN 非常確信,無論它所看到的是什么,都是數字 4):

          // a possible payload for resultToConvert - this data came from the DNN
          {
              Zero: 0.1927014673128724,
              One: 1.588071696460247,
              Two: 0.09038684074766934,
              Three: 0.0014367527001013514,
              Four: 94.81642246246338,
              Five: 0.8259298279881477,
              Six: 0.10091685689985752,
              Seven: 0.46726344153285027,
              Eight: 0.30299206264317036,
              Nine: 41.01988673210144
          }

          我們使用此輸出來構建一個新數組,其中每個項目都有一個標簽屬性(我們創建并分配單詞值,如“Zero”,“One”等),一個可能性屬性(存儲從該項的神經網絡接收的概率),一個topChoice屬性(我們計算)和一個序號屬性(我們為其賦值, 如 0, 1, 2-9)。

          我們按可能性對數組進行排序,以確定 DNN 的首選,然后使用此信息用 1(真)或 0(假)標記該項目的 topChoice 屬性。作為最后一步,我們采用新構造的數組并將其饋送到最終函數 - arrayToHTML() - 該函數將此信息包裝在HTML標記中:

          function arrayToHTML(arr) {
              let htmlToReturn=''
              htmlToReturn=arr.map(x=> {
                  let styleToUse=x.topChoice===1 ? 'background-color: yellow;' : ''
                  return `<div style="${styleToUse}">${x.label} Confidence: ${x.likelihood * 100}%</div>`
              }).join('')
          
              return htmlToReturn;
          }

          除其他操作外,此函數還對它收到的每個項目執行檢查,以確定其 topChoice 屬性是否為 1。如果是,則用黃色標記包裝項目。這是我們在網頁上看到的突出顯示。

          有了這個,我們已經看到了從UI到DNN(作為用戶輸入)和再次返回(作為中繼到UI的DNN輸出)的完整往返。

          步驟4. 建立 Brain.js 神經網絡對象Set up Brain.js neural-network object

          早些時候,我們指出,Brain.js庫使我們能夠創建的DNN對象需要一些設置才能使用它。我們將在這里詳細討論這個問題。

          number-evaluator.html文件中,我們創建了一個名為 activate() 的函數。當 HTML 文檔最初加載時,這將觸發,并且我們在此函數中定義、創建和訓練 DNN。

          我們通過調用 Brain.js庫中的 NeuralNetwork() 方法來做到這一點,就像這樣(brain是我們從 Brain.js 庫的本地副本中可用的變量,存儲在本地brain.js文件中):

          // setting up a BrainJS DNN object with two specified hyper parameters
          ourNeuralNetwork=new brain.NeuralNetwork({
              activation: 'sigmoid',
              learningRate: 0.1
          })

          Hyper parameters 初始參數

          當數據科學家和機器學習工程師創建神經網絡時,他們通常需要提供一組初始值,用于說明網絡在訓練時的運行方式。這些初始值或參數稱為超參數。

          它們控制神經網絡調整學習方式的速度,在其隱藏層中使用哪種操作,以及許多其他方面。在其他語言和設置中,我們通常需要提供許多超參數來訓練神經網絡。然而,有了Brain.js,我們根本不需要提供任何東西。如果省略任何超參數,該庫將提供默認值。

          在上面的示例中,我們指定了兩個超參數。第一個是一個名為激活的參數,我們已將其設置為 sigmoid。激活函數是神經網絡在其隱藏層中執行的東西,用于處理從一層到下一層的輸入。它們對于幫助神經網絡學習至關重要,因為它們有助于控制哪些節點應該繼續觸發,哪些節點應該在每一層中保持沉默。乙狀體是一種激活函數。我們可以使用許多品種(ReLU,譚等)。每個激活函數都有自己的優點和缺點。使用 sigmoid 對于分類之類的事情特別有用,這是我們在本教程中要實現的目標。

          我們指定的另一個超參數是學習速率。學習速率決定了神經網絡在嘗試創建有用的預測模型時(即,當它試圖學習如何區分3和7時)調整其值的速度(或速度)。

          指定學習速率,就像指定其他超參數一樣,既是藝術,也是科學:如果將速率設置得太低,您的網絡可能需要不可接受的時間來訓練,例如,如果您在云服務上租用GPU,這可能會產生真正的財務后果;如果您將速率設置得太高,您的網絡可能永遠不會收斂到所謂的“全局最小值”(解決方案)。

          時間和實踐將使您能夠掌握良好的初始值是什么樣子的。

          步驟5.訓練神經網絡 Training our neural network

          我們一直在談論神經網絡的學習以及我們必須如何訓練它,但這意味著什么,它看起來是什么樣子的?在我們的教程應用程序的上下文中,培訓如下所示:

          const ourTrainingData=getTrainingData()
          ourNeuralNetwork.train(ourTrainingData)

          訓練是 DNN 工作原理的基礎。通常,它的完成方式是使用監督學習方法:我們提供一個數據集,其中包含示例輸入和答案(或標簽,有時也稱為真實標簽),用于描述該數據行的正確分類。當我們訓練一個DNN(大腦.js允許我們從有用的命名train()方法開始,它使用這些標簽來幫助它學習。

          步驟 6. 準備訓練數據Train the data

          查看 getTrainingData() 函數,我們可以知道DNN具體是如何工作的。

          Brain.js允許我們通過訓練數據來指定我們的輸入數據將是什么樣子的,以及我們希望從神經網絡中看到什么樣的輸出。它的主要要求是我們提供輸入和輸出屬性。有關詳細信息,請參閱“訓練選項”下的“大腦.js GitHub 存儲庫”。

          下面是訓練數據樣例

          { "input": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 
              "output": { 
                  Zero: 1, 
                  One: 0, 
                  Two: 0, 
                  Three: 0, 
                  Four: 0, 
                  Five: 0, 
                  Six: 0, 
                  Seven: 0, 
                  Eight: 0, 
                  Nine: 0 
                  } 
              }

          訓練識別概率

          {
              Zero: 0.1927014673128724,
              One: 1.588071696460247,
              Two: 0.09038684074766934,
              Three: 0.0014367527001013514,
              Four: 94.81642246246338,
              Five: 0.8259298279881477,
              Six: 0.10091685689985752,
              Seven: 0.46726344153285027,
              Eight: 0.30299206264317036,
              Nine: 41.01988673210144
          }


          自己創建訓練數據

          通過手寫板準備數據,

          Summary 總結

          本文中,我們展示了如何使用 JavaScript 實現和訓練 DNN,這要歸功于brain.js庫 - 通常需要 Python 和 Keras、Pytorch 或 TensorFlow 等庫的任務。

          我們證明了一個有效的數字識別器可以用令人驚訝的少代碼創建。我們學習了機器學習的一些基本構建塊和實踐,例如為DNN指定學習速率和激活函數(以及其他超參數)。

          希望本文已經向您展示,在沒有經驗的情況下開始使用AI和機器學習不僅是可能的,而且在像JavaScript這樣的熟悉語言中也是可行的。

          TML 顏色


          HTML 顏色由紅色、綠色、藍色混合而成。


          顏色值

          HTML 顏色由一個十六進制符號來定義,這個符號由紅色、綠色和藍色的值組成(RGB)。

          每種顏色的最小值是0(十六進制:#00)。最大值是255(十六進制:#FF)。

          這個表格給出了由三種顏色混合而成的具體效果:

          1600萬種不同顏色

          三種顏色 紅,綠,藍的組合從0到255,一共有1600萬種不同顏色(256 x 256 x 256)。

          在下面的顏色表中你會看到不同的結果,從0到255的紅色,同時設置綠色和藍色的值為0,隨著紅色的值變化,不同的值都顯示了不同的顏色。



          灰暗色調

          以下展示了灰色到黑色的漸變


          Web安全色?

          數年以前,當大多數計算機僅支持 256 種顏色的時候,一系列 216 種 Web 安全色作為 Web 標準被建議使用。其中的原因是,微軟和 Mac 操作系統使用了 40 種不同的保留的固定系統顏色(雙方大約各使用 20 種)。


          我們不確定如今這么做的意義有多大,因為越來越多的計算機有能力處理數百萬種顏色,不過做選擇還是你自己。

          最初,216 跨平臺 web 安全色被用來確保:當計算機使用 256 色調色板時,所有的計算機能夠正確地顯示所有的顏色。

          代 CSS 顏色規范

          新的 CSS Color Module 規范引入了多種新的顏色表示法. 可以支持多種色彩空間和顏色模型. 這解鎖了很多的玩法. 比如: 基于一個顏色生成更深或更淺的顏色; 根據背景自適應文本色; 使用廣色域顏色等等.

          CSS Color Module Level 4 規范

          引入了新的顏色表示法, 同時引入了多種色彩空間, 不再僅限于sRGB, 這些方法現代瀏覽器均已支持:

          • 基于 sRGB 色彩空間的方法: hsl(), hwb(), rgb();
          • 基于 CIELAB 色彩空間的方法: lab(), lch();
          • 基于 Oklab 色彩空間的方法: oklab(), oklch();
          • 其它色彩空間的方法: color()

          再補充一點, 這些新方法中:

          • 帶 h 的是使用極坐標的顏色空間: hsl, hwb, lch, oklch
          • color()使用任意 color-gamut CSS 媒介功能支持的顏色空間
          • 其它使用的是直角坐標系的顏色空間: rgb, lab, oklab

          CSS Color Module Level 5 規范

          • 引入工具方法: color-mix(), 現代瀏覽器均已支持.
          • 擴展CSS Color Module Level 4 引入的新方法, 是它們支持相對顏色表示法. 相對顏色表示法絕大多數現代瀏覽器已支持.

          CSS Color Module Level 6 規范

          • 引入工具方法: color-contrast(), 目前還沒有瀏覽器支持, 但使用Level 4和Level 5中的工具和方法就可以實現.

          在詳細介紹這些現代新方法之前有必要對一些術語進行解釋:

          名詞解釋:

          • 顏色模型(color model)

          顏色模型是指顏色與坐標系之間的映射和編碼方式, 它定義維度分量與色彩空間的關系. 一個顏色模型就會有一個對應的色彩空間.

          • 色彩空間(color space)

          色彩空間是某一顏色模型所涵蓋的顏色的定義和命名. 每個顏色空間都由數學模型和關聯的規則集定義. 色彩空間是表示顏色的三維網格, 色彩空間中的每個顏色都由三個通道分量(維度)來表示. 每個顏色空間都有一個定義的色域。

          • 色域(color gamut)

          色域指的是它可以表示的特定顏色的范圍, 通常指設備可以顯示的顏色范圍. 如 sRGB, P3, Rec2020 等

          可以看出三者有一些共性的東西, 通常來說, 當上下文中使用顏色空間時強調的是它的顏色模型和算法. 當使用色域時強調的是能不能顯示某些顏色

          所有色彩空間

          CSS Color Module Level 4 新引入的顏色方法統一了帶和不帶alpha通道的表示法

          比如, 以前用的最多的rgb方法, 帶和不帶alpha通道是不同的方法: 不帶alpha通道的是: rgb(r, g, b), 而帶alpha通道的是: rgba(r, g, b, a)

          現在可以統一使用: rgb(R G B [/ A]), alpha通道值是可選的. 注意為了區分舊方法, 新方法不使用逗號分隔分量, 而是用空格替代.

          上面只是拿rgb方法舉了個例子, 其實Level 4 中的所有新方法都支持這種表示法. 如: oklch(L C H [/A])

          CSS Color Module Level 5 相對顏色表示法

          語法: rgb(from <color> R G B[ / A]), hsl(from <color> H S L [/A]), oklch(from <color> L C H [/A]), ...

          相對顏色是指從一個指定顏色的色彩空間轉換到目標色彩空間, 通過對目標色彩空間中的維度變量進行微調后的結果作為輸出.

          這聽起來比較繞, 簡單點說就是可以根據原色, 對維度變量進行微調后輸出. 主要特性:

          1. 可以從任意色彩空間轉換到目標色彩空間, 甚至是CSS自定義屬性.
          2. 轉換后可以使用目標色彩模型中的維度變量
          3. 維度分量可以使用calc()等CSS函數計算

          這3個特性解鎖了一些原本只能通過js才能實現的一些功能.

          例子1: 鼠標覆蓋按鈕時加深背景色:

          方法1: 使用Level 5 規范中的相對顏色表示法:

          .btn {
            --btn-bg: blue;
            background-color: var(--btn-bg);
          }
          .btn:hover {
            background-color: oklch(from var(--btn-bg) calc(l - 0.1) c h);
          }

          這個例子中--btn-bg自定義屬性可以更改為任意顏色, 本例中使用了oklch作為目標色彩空間, 因為oklch可以做到調整亮度而不會影響色相.

          從這個例子中可以看出, CSS自定義屬性與相對顏色的結合使用, 可以創造出很多的新玩法.

          方法2: 使用Level 5 規范中的color-mix()方法

          .btn {
            --btn-bg: blue;
            background-color: var(--btn-bg);
          }
          .btn:hover {
            background-color: color-mix(in oklch, var(--btn-bg), black 10%);
          }

          color-mix()方法的意思是將顏色1和顏色2先轉換到in關鍵字指定的目標色彩空間, 然后按百分比混合它們后輸出.由于black只有L分量, 因此混合只影響了L分量, 因此就得到了不改變色相的情況下加深了顏色.

          例子2: 根據不同背景色自適應高對比度的文本色

          這個場景需要一種方式確定高對比度的算法模型. 通用的是WCAG 2.1, 但它不太準確, 還有一種是APCA, 它相對準確性更高, 參考性更大. 在APCA算法下, 采用oklch顏色模型下L分量在72%左右是一個比較好的對比度分界線. 72%以上采用黑色文本, 72%以下采用白色文本.

          好了, 有了這個基礎, 現在可以使用純CSS實現自適應高對比度的文本色:

          .btn {
            --btn-bg: blue;
            background-color: var(--btn-bg);
            color: oklch(from var(--btn-bg) clamp(0, calc((0.72 - l) * 10000), 1) 0 0);
          }

          這個例子中--bg自定義屬性可以更改為任意顏色, 按鈕文本都可以自適應的高對比度顏色. 本例中使用了oklch作為目標色彩空間, 因為oklch可以做到亮度是可預測性.

          這里稍微解釋這句:clamp(0, calc((0.72 - l)* 10000), 1), 意思是背景色的l維度分量 > 0.72說明背景是淺色的, 那么文本色的L分量就取0即黑色, 否則就說明背景是深色的,L分量就取1即白色. 如果不想純白或純黑, 適當調整各分量以及L的上下界即可.

          這個例子還可以使用CSS Color Module Level 6中的color-contrast()實現相同的效果, 但目前還沒有瀏覽器支持, 留著將來備用:

          .btn {
            --btn-bg: blue;
            background-color: var(--btn-bg);
            color: color-contrast(var(--btn-bg) vs white,black);
          }

          color-contrast()的意思是選擇vs關鍵字之后與第一個參數指定的顏色對比度最高的顏色作為輸出.

          這么多CSS顏色新方法, 我應該使用哪個?

          現代網頁中推薦使用oklch顏色模型, 使用 OKLCH 的好處:

          • OKLCH 各分量是獨立的,互不影響的, 對一個分量的修改不會影響其它分量. 而 hsl()不是.
          • OKLCH 使設計師無需手動選擇每種顏色。他們可以定義一個公式,選擇幾種顏色,并自動生成整個設計系統調色板。
          • OKLCH 可用于任意色域, 標準色域 sRGB, 廣色域 P3, Rec2020 等。例如,新設備(如 Apple 的設備)可以顯示比舊 sRGB 顯示器更多的顏色,我們可以使用 OKLCH 來指定這些新顏色。而且超出色域瀏覽器會呈現最接近的顏色
          • 與 hsl() 不同,OKLCH 更適合顏色修改和調色板生成。因為它使用的是感知亮度, 因此不會再出現意想不到的結果,比如在 Sass 中使用 darken() 產生的意外結果。
          • 憑借其可預測的亮度 L, OKLCH 提供了更好的 a11y。
          • 隨著 CSS 相對顏色函數的瀏覽器普及, 可以很方便的微調顏色(比如根據基色生成強調色, 只需修改 L 分量), 也將不再需要js偵測背景色的高對比度文本色. 根據 APAC 對比度算法,在感知亮度 L >=72% 時所有色相下黑色文本都不會產生對比度的可訪問性問題.
          • 與 rgb() 或十六進制(#ca0000)不同,OKLCH 是人類可讀和可預測的。您只需查看數字即可快速輕松地知道 OKLCH 值代表哪種顏色。OKLCH 的工作方式類似于 HSL,但它對亮度的編碼比 HSL 更好。

          OKLCH 顏色由亮度(明度)、色度(飽和度或純度)、色相三個維度組成, 這也是人類認知里的顏色的三個基本屬性.

          • 亮度(lightness) 是感知亮度,取值: 0-1 或 0-100%,0為黑色,1或100%為白色,"感知"意味著它對我們的眼睛具有一致的亮度,并且是可預測的, 這與 hsl()中的 L 是不同的。
          • 色度(chroma) 從灰色到最飽和的顏色, 對于 P3 和 sRGB 顏色空間應低于 0.37, Rec2020 顏色空間應低于 0.4
          • 色相(hue) 在色環中的角度, 色環: 紅、橙、黃、綠、青、藍、紫。紅為20度左右, 每個顏色間隔50度左右.

          詳細分析請看這篇文章: OKLCH in CSS: why we moved from RGB and HSL—Martian Chronicles, Evil Martians’ team blog

          為了兼容性考慮或想在js中使用CSS相同的顏色功能怎么辦?

          使用這個 colorjs.io npm包即可. 它完全支持CSS Color Module Level 4 和 Level 5 的規范

          新的CSS Color Module規范產生的影響:

          1. 瀏覽器原生的顏色選取器元素需要更新以支持新的顏色模型, 目前還沒有瀏覽器實現.
          2. 現有第三方的顏色選取器組件都是基于sRGB的, 不能選取新的色彩空間中的顏色. 這些組件需要重構.

          我們的正式開源輕量級的基于Tailwindcss的React 組件庫中的顏色選取組件正在重構中


          主站蜘蛛池模板: 爆乳熟妇一区二区三区霸乳| 国产一区二区免费| 久久久av波多野一区二区| 无码精品人妻一区二区三区漫画 | 久久亚洲国产精品一区二区 | 国产精品一区三区| 中文无码精品一区二区三区 | 大香伊蕉日本一区二区| av无码免费一区二区三区| 亚洲乱码日产一区三区| 国产视频一区二区在线播放| 欧美av色香蕉一区二区蜜桃小说| 欧洲精品一区二区三区在线观看 | 亚洲一区二区三区影院| 国产伦精品一区二区三区精品| 亚洲一区二区三区国产精品无码| 国产成人一区二区三区在线| 国产在线精品一区二区夜色| 国产av天堂一区二区三区| 国产在线步兵一区二区三区| 另类国产精品一区二区| 日本精品3d动漫一区二区| 亚洲宅男精品一区在线观看| 亚洲熟女综合色一区二区三区 | 亚洲一区免费在线观看| av无码免费一区二区三区| 成人久久精品一区二区三区| 国产亚洲综合精品一区二区三区| 日本免费一区尤物| chinese国产一区二区| 国产成人精品一区二区三区免费| 中文字幕一区二区三区日韩精品| 免费播放一区二区三区| 国产精品一区二区三区高清在线| 亚洲国产精品一区二区第一页免 | 冲田杏梨高清无一区二区| 日本不卡一区二区视频a| 国产一区二区久久久| 久久一区二区免费播放| 激情无码亚洲一区二区三区| 国产激情一区二区三区|