我在另外一個demo中,須要用到color picker,可是找不到我須要的移動端color picker,不少都是pc的,而後發現input[type='color']這個東西存在,發現安卓沒問題,ios卻不支持,可是我看安卓那個color picker貌似很簡單就能實現,恰好另外一個demo也是用canvas實現的,因此就打算本身寫一個。css
項目演示地址html
效果大概就是這樣。外層選擇顏色,內層就是混合的。ios
這裏有兩部分,一個是圓環,一個是正方形,兩個形狀內都有兩個點,這兩個點表示當前選擇的顏色。圓環的選擇的顏色,決定正方形顯示的顏色,正方形內的點,決定最終輸出的顏色。git
因此我先製做圓環和正方形的顏色,而後給畫布事件獲取鼠標位置。再使用canvas的getImageData,咱們只須要ctx.getImageData(x,y,1,1)
就能夠獲取到rgba顏色了。github
製做這個圓環,一開始想到是用漸變來處理的,但不管線性仍是徑向,都好像搞不出來,而後我google了下,使用線和hsl就能夠搞出來了。咱們這裏製做的圓環,是一個圓形,這裏就能夠用循環360,根據每次循環的度數,去製做線。而顏色就是hsl(i , 100% , 50%)
這樣就能夠獲得顏色。canvas
咱們看看hsl是怎麼組成的。
H:Hue(色調)。0(或360)表示紅色,120表示綠色,240表示藍色,也可取其餘數值來指定顏色。取值爲:0 - 360
S:Saturation(飽和度)。取值爲:0.0% - 100.0%
L:Lightness(亮度)。取值爲:0.0% - 100.0%yii
咱們只需改變H(色調)就能夠製造出經常使用的顏色出來。函數
canvas中的mveTo和lineTo,須要x,y座標,才能製做出一條線,再經過hsl顏色,進行繪製。這裏獲取x,y座標,用到了三角函數,Math.sin,Math.cos
。要注意的是,它們接受的值是弧度,而不是角度,因此咱們要先把角度轉成弧度先rad = i * (2 * Math.PI) / 360
。this
看這圖,應該能大概知道了x,y座標的獲取,不過這裏獲取的x,y是相對於圓心的距離,而不是相對於(0,0)這個點,因此咱們還要加上半徑r,纔是最終的x,y座標。google
for (var i = 0; i < 360; i += .1) { //獲取度數 var rad = i * (2 * Math.PI) / 360; //計算x,y座標 x = r + Math.cos(rad) * r; y = r + Math.sin(rad) * r; //而後鏈接線 ctx.strokeStyle = "hsl(" + i + ", 100%, 50%)"; ctx.beginPath(); ctx.moveTo(r,r); ctx.lineTo(x,y); ctx.stroke(); ctx.closePath(); }
這樣就能夠製做出漸變色的圓形,但卻不是圓環,由於中間是透明,沒有顏色的(也不能是白色)。本來我打算再繪製一個白色圓來覆蓋中間部分的,但我想要的是透明的效果,這樣看起來會好不少。因此繼續在上面循環作文章了。
既然終點能夠計算,那起點也是一樣的道理,只不過加的長度不一樣而已。
for (var i = 0; i < 360; i += .1) { //獲取度數 var rad = i * (2 * Math.PI) / 360, angleX = Math.cos(rad), angleY = Math.sin(rad), lineW = 20;//圓環的厚度 //而後鏈接線 ctx.strokeStyle = "hsl(" + i + ", 100%, 50%)"; ctx.beginPath(); //計算座標 ctx.moveTo(r + angleX * (r - lineW),r + angleY * (r - lineW)); ctx.lineTo(r + angleX * r,r + angleY * r); ctx.stroke(); ctx.closePath(); }
這樣就能夠製做出圓環的效果,並且中間的圓形是透明的。
這裏是用了三種顏色疊加起來的。首先是從圓環獲取到的顏色,加上從左到右的白色漸變色,加上從下到上的黑色漸變色。每當圓環的顏色改變後,要從新生成正方形的顏色。
接着,就要給canvas添加事件了,來判斷手指移動的座標,是否在圓環或者正方形內,而後根據這個座標去生成顏色。
這裏就主要說下,怎麼判斷移動時,是否在圓環內。
移動時,經過事件對象event,能夠獲取到x,y座標
var t = event.touches[0], x = t.pageX - oCan_left, y = t.pageY - oCan_top;
這裏獲取到x,y座標還要減去畫布到可視區的左,上的距離。由於咱們計算的時候,是根據畫布的座標計算的,(0,0)座標就是畫布的左上角。
接着咱們來計算,這個x,y座標到圓心的距離d = Math.sqrt(Math.pow((x - r),2) , Math.pow((y - r),2))
。這裏用的是知道兩點座標,獲得兩點之間的距離,公式是這樣的d = √(x1 - x2)² + (y1 - y2)²
如上圖,畫布寬高其實就是外圓的直徑,r1*2。開始點(0,0)在左上角。咱們移動的座標,到圓心的距離d,小於r1且大於r2的話,就是在圓環內了。d >= r2 && d <= r1
這個簡單,獲得了x,y座標後就能夠直接獲取顏色了,直接上代碼
var pixel = this.ctx.getImageData(x, y, 1, 1), data = pixel.data, rgb = 'rgb(' + data[0] + ',' + data[1] + ',' + data[2] + ')'; return rgb
我已經把代碼上傳到github了,你們能夠下載使用。
只要把colorPicker.js和colorPicker.css導入就行了。按下面代碼調用便可:
//html結構 <div class='colorPickerbox'> <canvas id='colorPicker'></canvas> <div class="colorPickerBtnWrap"></div> </div> //調用代碼 new ColorPicker({ oBox: document.querySelector('.colorPickerbox'),//最外層 oBtnWrap: document.querySelector('.btnWrap'),//按鈕外層 oCan: document.querySelector('#colorPicker'),//畫布 width: 200,//畫布寬高 height: 200, callback:function(color){//回調函數 //color就是獲取到的顏色 } }).init()//初始化
這個color picker我用了一個下午左右的時間,大概完成了。主要是生成顏色區域,判斷手指移動所在的區域,這兩塊花了多點的時間。並且用到了三角函數,還有一些座標計算啊,數學都已經還給了老師,要多寫下這種demo,順便來複習下數學。
能夠用canvas來處理的東西太多了,看來是要花更多的時間在canva這部分,由於確實挺有趣的 :)