使用canvas製做的移動端colorPicker

使用canvas製做的移動端color picker

我在另外一個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

咱們看看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) / 360this

看這圖,應該能大概知道了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這部分,由於確實挺有趣的 :)

這裏是原文地址

相關文章
相關標籤/搜索