取色網站
前幾天遇到了獲取圖片主題色的需求,於是去找了一些相關的部落格,發現實現起來相當簡單,於是自己開發了一個獲取圖片主題色的網站---ColorfulImg 大家可以通過上傳/拖拽圖片的方式獲取圖片主題色。歡迎Star~
ColorfulImg
Colorfulimg是一個能夠通過canvas獲取圖片主題色的js工具庫。
安裝:
npm i colorfulimg
使用方法:
let colorfulimg = require('colorfulimg')
let myImg = document.getElementById('myImg')
let rgb = colorfulImg(myImg);
複製程式碼
歡迎star~
ColorfulImg實現思路
下面說一下實現思路,主要是通過canvas的getImageData()方法獲取圖片每個畫素點的rgba資料。通過取得平均值的方法來算出圖片主題色。 所以要想實現此效果有兩個限制:
- 網站和圖片必須是相同的域名(getImageData()限制圖片必須同源)
- 瀏覽器必須支援canvas
在canvas中繪製img影像
- 首先我們要新建一個canvas標籤並且訪問它的繪畫上下文:
let canvas = document.createElement('canvas')
let context = canvas.getContext && canvas.getContext('2d')
複製程式碼
- 繪製img影像,X軸與Y軸的起始點都設定為0:
let myImg = document.getElementById('myImg')
context.drawImage(myImg , 0, 0)
複製程式碼
獲取圖片顏色資料getImageData()
getImageData()這個API需要四個引數,前兩個是獲取圖片資料的起點,後兩個是提取的影像資料矩形區域的寬度和高度,我們要得到圖片全部的資料所以後兩個引數就是圖片的寬高,於此同時我們也要把canvas的寬高設定為圖片的寬高能完全裝下圖片。
let height = canvas.height = imgEl.height
let width = canvas.width = imgEl.width
let data = context.getImageData(0, 0, width, height).data
複製程式碼
在我第一次測試的時候遇到了跨域的問題:
圖片如果不同源的話必須要加crossorigin="anonymous"
的屬性,並且伺服器儲存那邊也要開放相應的許可權才行。
<img id="img" crossorigin="anonymous">
處理獲取的顏色資料
我們先log一下拿到的資料是什麼吧:
是一個有著一堆資料的陣列,這些資料是什麼呢?我們先看一下MDN:
也就是說按順序來看前四位組成一個以RGBA順序的資料: rgba(red, green, blue, alpha)
對於獲取的圖片資料透明度(alpha)都是255也就是不透明的所以我們不對透明度做處理,之後我們只需要把rgb的其他三個值分別求和再取均值就可以得到圖片的主題色了!
let count = 0
let i = 0
let blockSize = 1
while ( (i += blockSize * 4) < length ) {
++count
rgb.r = data[i] + rgb.r
rgb.g = data[i+1] + rgb.g
rgb.b = data[i+2] + rgb.b
}
rgb.r = ~~(rgb.r/count)
rgb.g = ~~(rgb.g/count)
rgb.b = ~~(rgb.b/count)
複製程式碼
最終程式碼
function colorfulImg(img){
let canvas = document.createElement('canvas'),
context = canvas.getContext && canvas.getContext('2d'),
height,width,length,data,
i = -4,
blockSize = 5,
count = 0,
rgb = {r:0,g:0,b:0}
height = canvas.height = imgEl.height
width = canvas.width = imgEl.width
context.drawImage(imgEl, 0, 0);
data = context.getImageData(0, 0, width, height).data
length = data.length
while ( (i += blockSize * 4) < length ) {
++count;
rgb.r += data[i];
rgb.g += data[i+1];
rgb.b += data[i+2];
}
rgb.r = ~~(rgb.r/count);
rgb.g = ~~(rgb.g/count);
rgb.b = ~~(rgb.b/count);
return rgb;
}
複製程式碼