紅包照片四不像(二)——canvas基礎(chǔ)

在前面一篇文章中,我們通過css的方式實現(xiàn)了紅包照片的模糊效果和偷窺鏡。
但是通過demo發(fā)現(xiàn),效果并不是特別好,尤其是移動設(shè)備上的 動畫性能實在無法接受。
也可以通過canvas來實現(xiàn)相同的效果,本篇先來了解一下canvas的使用。

一、canvas基礎(chǔ)

1、canvas本質(zhì)

a.標(biāo)簽;
b.畫布;

2、基本使用

var canvas = document.getElementById('canvas_id'); //獲取canvas
canvas.height = document.documentElement.clientWidth; //設(shè)置寬高
canvas.width = document.documentElement.clientHeight;
var context = canvas.getContext('2d'); //獲取2d繪圖context

context.beginPath();  
  ...... //繪圖路徑
context.closePath();

context.fillStyle = ‘red'; //填充樣式,描邊樣式使用strokeStyle
context.fill(); // 填充繪圖,描邊繪圖使用stroke()

3、基礎(chǔ)API(路徑)

context.moveTo(x,y) // 確定起點
context.lineTo(x,y) // 繪制線段
context.fillRect(x,y,width,height) // 填充矩形
context.strokeRect(x,y,width,height) // 描邊矩形
// 繪制圓弧,參數(shù)包含圓心坐標(biāo)/半徑/起止弧度點/弧度行進方向
context.arc(x, y, radius, starAngle,endAngle, anticlockwise)

context.clearRect(x,y,width,height) //清除畫布某矩形區(qū)域

// 貝塞爾曲線
context.quadraticCurveTo(qcpx,qcpy,qx,qy)
context.bezierCurveTo(cp1x,cp1y,cp2x,cp2y,x,y) 

// 漸變,起始點以及偏移點點顏色
var lGradient = context.createLinearGradient(xStart,yStart,xEnd,yEnd) // 線性
var rGradient = context.createRadialGradient(xStart,yStart,radiusStart,xEnd,yEnd,radiusEnd) // 徑向
*Gradient.addColorStop(offset,color)

context.translate(x,y) // 平移
context.scale(x,y) // 縮放
context.rotate(angle) // 旋轉(zhuǎn)
// 備注:以上三個變化操作的不是繪圖,而是坐標(biāo)軸

context.globalCompositeOperation=type //圖形組合
/*    type:
        source-over(默認值):在原有圖形上繪制新圖形
        destination-over:在原有圖形下繪制新圖形
        source-in:顯示原有圖形和新圖形的交集,新圖形在上,所以顏色為新圖形的顏色
        destination-in:顯示原有圖形和新圖形的交集,原有圖形在上,所以顏色為原有圖形的顏色
        source-out:只顯示新圖形非交集部分
        destination-out:只顯示原有圖形非交集部分
        source-atop:顯示原有圖形和交集部分,新圖形在上,所以交集部分的顏色為新圖形的顏色
        destination-atop:顯示新圖形和交集部分,新圖形在下,所以交集部分的顏色為原有圖形的顏色
        lighter:原有圖形和新圖形都顯示,交集部分做顏色疊加
        xor:重疊部分不顯示
        copy:只顯示新圖形
*/

// 陰影
context.shadowOffsetX = 10;
context.shadowOffsetY = 10;
context.shadowColor = 'rgba(100,100,100,0.5)';
context.shadowBlur = 1.5;

// 繪制文字
context.fillText(text,x,y)  
context.strokeText(text,x,y)

// 畫筆畫布狀態(tài)暫存
context.save()
context.restore()

context.drawImage // 繪圖——下面單獨介紹

二、繪圖api相關(guān)

1、api介紹

context.drawImage(image, x, y, w, h) // Image對象、起始坐標(biāo)、繪制寬高(可省略)

context.drawImage(image,sx,sy,sw,sh,dx,dy,dw,dh)// 將Image的sx、sy位置sw、sh大小的圖像繪制再畫布dx、dy位置dw、dh大小的地方

context.fillStyle = context.createPattern(image,type)
/*  type:   no-repeat:不平鋪
          repeat-x:橫方向平鋪
          repeat-y:縱方向平鋪
          repeat:全方向平鋪   */

context.clip() // 設(shè)置繪制的封閉區(qū)域

// imagedata中每4個元素代表一個像素的rgba數(shù)據(jù),對應(yīng)圖像從左到右從上到下的像素
var imagedata=context.getImageData(sx,sy,sw,sh)
context.putImageData(imagedata,dx,dy,dirtyX,dirtyY,dirtyWidth,dirtyHeight) 

2、上帝繪圖模式

由于可以獲取到圖片每個像素的數(shù)據(jù),包括rgba,可以通過改變?nèi)魏蜗袼氐闹禐槿魏沃祦磉_到預(yù)期的效果。(just like the God)
那么我們究竟可以做些什么呢?
一般情況下,可以通過像素色彩的計算實現(xiàn)PS中一些比較簡單的濾鏡效果,例如灰度圖片只需要對單個像素的rgb值做加權(quán)平均就可以了,紅色圖片只需要把每個像素的r值設(shè)置為255即可。
下面詳細介紹幾種簡單的算法。

三、濾鏡算法

1、灰度

// 一般采用加權(quán)平均值,權(quán)值可以任意選取,常用 0.3、0.59、0.11;
r = g = b = r * rWeight + g * gWeight + b * bWeight; 
// 也可以使用其他的一些技巧,例如MAX
r = g = b = Math.max(r, g, b); 

2、灰度加強

r =(2*g - b + r)* r / 255;
g =(2*b - g + r)* r / 255;
b =(2*b - g + r)* g / 255;
... //再做灰度處理

3、反色——底片效果

r = 255 - r;
g = 255 - g;
b = 255 - b;

4、黑白

var temp = r * rWeight + g * gWeight + b * bWeight; // 可以采用灰度中的多種方式
r = g = b = temp > 128 ? 255 : 0; // 這里的取值也可以靈活處理,達到不同的黑白灰的效果

5、斑駁

r = r > 128 ? 255 : 0;
g = g > 128 ? 255 : 0;
b = b > 128 ? 255 : 0;

6、懷舊

r = r * 0.393 + g * 0.769 + b * 0.189; 
g = r * 0.349 + g * 0.686 + b * 0.168; 
b = r * 0.272 + g * 0.534 + b * 0.131; 

7、色彩通道——純色通道

// 純色比較簡單,包括一些單色通道和混合通道
r = 255; // 紅色
r= g = 255; // 黃色(紅+綠)
r = 0;// 反紅色,有別于(綠+藍)
// 這種方式比較靈活,可以通過調(diào)整rgb為任意常數(shù)值,來實現(xiàn)一些特別的效果

8、銳化

// rgb的值均加上當(dāng)前位置的顏色值與四面八方顏色值的差為當(dāng)前值
function getColor(color) {
      color[i][j] *= 10;
      for (var row = -1; row < 2; row++) {
            for (var col = -1; col < 2; col++) {
                  color[i][j] -= color[i + row][j + col];
            }
      }
}

9、馬賽克

// 某個方塊中所有像素的值取同一個位置的值
for (var i=0; i< Height; i++) {
    for (var j=0; j<Width; j++) {
        var iTemp = i - i % RADUIS;
        var jTemp = j - j % RADUIS;
        r[i * Width + j] =  r[iTemp * Width + jTemp];
        g[i * Width + j] =  g[iTemp * Width + jTemp];
        b[i * Width + j] =  b[iTemp * Width + jTemp];
   }
}

10、模糊

// 每個像素的值均取周圍像素值的平均值
for (var i=0; i< Height; i++) {
    for (var j=0; j<Width; j++) {
        color[i * Width + j] =  getColor(i, j);
   }
}
function getColor(i, j) {
    var result = 0, count = 0;
    for (var m = i - RADUIS;m < i + RADUIS; m++) {
          if (m < 0) {               continue;        }
          for(var n = j - RADUIS; n < j + RADUIS; n++) {
              if (n < 0) {            continue;        }
              result += data[m * width + n];
              count++;
          }
      }
      return result/count;
}

11、浮雕

// 相鄰點的差值做類似半灰度的處理
for (var i=0; i< Height; i++) {
    for (var j=0;j<Width;j++) {        
        r[i* Width + j] = r[(i* Width + j) + 1] - r[i* Width + j] + 128;
        g[i* Width + j] = g[(i* Width + j) + 1] - g[i* Width + j] +128;
        b[i* Width + j] = b[(i* Width + j) + 1] - b[i* Width + j] +128;
        ... //再做灰度處理(可能會有一些彩色的線條,可以通過灰度處理去掉)
     }
}

四、濾鏡示例

Just Load:http://tkixp9.github.io/redbag/draw_image_as_god.html 。

五、canvas實現(xiàn)紅包照片

TO BE CONTINUED...

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容