相識HTML5 canvas


Canvas是HTML的API,我們可以用它在網頁中實時的來生成圖像。

文章導讀

  1.必備技能

  2.用於畫圖的函數

    例子:

      -會話氣泡-    -心形-    -鍾表-      -星球里的星星-

      -調色板-      -鼠標繪圖-      -旋轉的小方塊-

  3.圖像的處理

    例子:

      -圖像的灰度和翻轉效果-     -拾色器-

      -放大鏡-      -圖像的高斯模糊-    

一.必備技能

<canvas id="Canvas" width="400" height="200">
    不支持canvas的瀏覽器,你就會看到這句話!
</canvas>

控制它的寬高是要寫在行內樣式中的,像上面那樣。這樣我們就有了一個canvas元素,然后我們就可以去操作它了:

var canvas = document.getElementById('Canvas');

if (canvas.getContext) {
    var content = canvas.getContext('2d');
}

獲取元素的同時,還要獲取canvas的2D繪圖環境。要是用於3D繪圖的話,就要用WebGL了。

 

二.用於畫圖的函數

然后,我們要開始在畫布上繪圖了。它的畫布是這樣的網格:

   

2.1矩形

canvas中只支持這一種形狀的函數,別的形狀就都要自己組合來實現了。

fillRect(x, y, width, height) //畫一個填充的矩形
strokeRect(x, y, width, height) //畫一個只有邊框的矩形
clearRect(x, y, width, height) //清除指定的矩形區域

其中的(x,y)是指矩形左上角的坐標。

查看源碼][運行結果

2.2路徑

1.首先,創建一條路徑--beginPath() 
2.然后,通過一些繪圖的方法做一些繪圖操作
3.然后關閉路徑--closePath()
4.我們已經把路徑創建好了,然后就是填充或者繪制路徑到我們的畫布上--stroke()/fill()

比如說畫一個三角形:

查看源碼][運行結果

需要注意的是其中兩個三角形,顏色不同,一不小心可能會出問題,所以我們有時可能需要save()和restore()函數的幫助來達到局部作用的效果。比如上面示例源碼中所做的那樣:

 1               
 2                content.save();//局部作用效果
 3                content.fillStyle = 'red';
 4          content.beginPath();//beginPath()不寫的時候可能會出錯,所以確保beginPath和closePath都相對應
 5          content.moveTo(100,100);
 6          content.lineTo(200,200);
 7          content.lineTo(300,200);
 8          content.closePath();
 9          content.fill();
10          content.restore();
11 
12 
13          content.beginPath();
14          content.moveTo(100,200);
15          content.lineTo(200,300);
16          content.lineTo(300,300);
17          content.closePath();
18          content.fill();
View Code

canvas還提供了兩個移動畫筆的函數:

moveTo(x, y) //將畫筆移動到指定的(x,y)的位置
lineTo(x, y) //在當前畫筆的位置到指定的(x,y)位置畫一條線

嘗試一下moveTo()方法我們可以畫個笑臉:

    

查看源碼][運行結果

結合使用moveTo和lineTo方法,我們可以實現鼠標像畫筆一樣在畫板上繪圖的效果:

查看源碼][運行結果

然后我們嚴格的按照上面說的規范步驟,1,2,3,4並結合畫圓的函數,可以自己繪制一個鍾表,稍加改進就是個嘀嗒嘀嗒走的時鍾了:

 

查看源碼][運行結果

 2.3文字

fillText('要顯示的文本',x坐標,y坐標)此方法不支持文本斷行,要顯示多行文本只能多次調用

通過fillText()方法我們可以在canvas畫布上寫文字:

查看源碼][運行結果

2.4圓形和扇形

ctx.arc(x, y, radius, startAngle, endAngle, anticlockwise);

(x,y)--圓心坐標
radius--半徑
startAngle--扇形的起始角度(弧度)
endAngle--扇形的終止角度(弧度)
anticlockwise--做圖時是順時針畫(true)還是逆時針(false)畫

查看源碼][運行結果

結合對rgb顏色的相關操作,我們可以做出類似調色板的效果:

         

查看源碼][運行結果

2.5不規則圖形

我們可以通過畫曲線來得到不規則的圖形,canvas為我們提供了兩個高大上的函數:

-------------------------------
#quadraticCurveTo(cp1x, cp1y, x, y) (cp1x,cp1y)--控制點 此函數表示從當前的畫筆位置到(x,y)畫一條二次曲線 ------------------------------- #bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y) (cp1x,cp1y)--控制點1 (cp2x,cp2y)--控制點2 此函數表示從當前的畫筆位置到(x,y)畫一條bezier曲線
-------------------------------

這兩個曲線具體含義我也不太清楚,但大概是這個樣子:

   

 

試一下quadraticCurveTo函數:

      

查看源碼][運行結果

試一下bezierCurveTo函數:

    

查看源碼][運行結果

2.6漸變和陰影

#漸變:
var myGradient = ctx.createLinearGradient(x1, y1, x2, y2); 
(x1,y1)--起點坐標  (x2,y2)--終點坐標
myGradient.addColorStop(0, "#BABABA"); 
--添加起始顏色
myGradient.addColorStop(1, "#636363");
--添加終止的顏色

-----------------------------

#陰影
ctx.shadowOffsetX = 10; // 設置水平位移
ctx.shadowOffsetY = 10; // 設置垂直位移
ctx.shadowBlur = 5; // 設置模糊度
ctx.shadowColor = "rgba(0,0,0,0.5)"; // 設置陰影顏色

一個也不太搭邊兒的例子,不管怎么說,也用到了漸變呢:

查看源碼][運行結果

這里面用到了clip()方法來實現星星,這跟某css屬性clip-path比較神似,我以前嘗試過:

請戳[源碼][示例

2.7變換

canvas中有我們熟悉的幾個變換函數:

translate(x, y) --平移
rotate(angle) --旋轉
scale(x, y) --縮放
transform(a, b, c, d, e, f) --變換
上面的變換函數是根據變換矩陣進行的:
   a   c   e
[ b   d   f ]
   0   0   1

簡單的小例子:

查看源碼][運行結果

 

三.圖像處理

var myImageData = ctx.createImageData(width, height);
ctx.getImageData(left, top, width, height);//讀取canvas的內容,返回一個對象且該對象有一個data屬性,可以供我們操作頁面的像素。
ctx.putImageData(myImageData, dx, dy);//將操作好的對象重新繪制在畫布中
ctx.drawImage(img, 0, 0); // 我們常用的drawImage方法,設置對應的圖像對象,以及它在畫布上的位置

通過getImageData()方法獲取到圖像對象,訪問它的data屬性就可以得到一個像素數組,我們對像素進行處理,使我們可以用canvas處理圖像。

3.1 灰度效果

灰度圖(grayscale)就是取紅、綠、藍三個像素值的算術平均值,這實際上將圖像轉成了黑白形式。假定d[i]是像素數組中一個象素的紅色值,則d[i+1]為綠色值,d[i+2]為藍色值,d[i+3]就是alpha通道值。轉成灰度的算法,就是將紅、綠、藍三個值相加后除以3,再將結果寫回數組。

1               for(var i=0;i<data.length;i+=4){
2                     var avg = (data[i]+data[i+1]+data[i+2]) / 3;
3                     data[i] = avg; //r
4                     data[i+1] = avg; //g
5                     data[i+2] = avg; //b
6                 }
View Code

3.2 復古效果

復古效果(sepia)則是將紅、綠、藍三個像素,分別取這三個值的某種加權平均值,使得圖像有一種古舊的效果。

1  for (var i = 0; i < d.length; i += 4) {
2       var r = d[i];
3       var g = d[i + 1];
4       var b = d[i + 2];
5       d[i]     = (r * 0.393)+(g * 0.769)+(b * 0.189); // red
6       d[i + 1] = (r * 0.349)+(g * 0.686)+(b * 0.168); // green
7       d[i + 2] = (r * 0.272)+(g * 0.534)+(b * 0.131); // blue
8     }
View Code

3.3 反轉效果

反轉效果(invert)是指圖片呈現一種色彩顛倒的效果。算法為紅、綠、藍通道都取各自的相反值(255-原值)。

1 for (var i = 0; i < d.length; i += 4) {
2         d[i] = 255 - d[i];
3         d[i+1] = 255 - d[i + 1];
4         d[i+2] = 255 - d[i + 2];
5     }
View Code

我嘗試了一下灰度圖的效果和反轉圖的效果:

查看源碼

注意,在我們自己本地寫demo准備運行查看結果的時候,getImageData()方法可能會有問題,比如說報這個錯:Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The canvas has been tainted by cross-origin data

我們知道這是域和本地運行等相關的問題,這時我們自己本地啟用服務器,localhost訪問就可以了。

 3.4 拾色器

實現思路:通過getImageData(x,y,1,1)獲得當前鼠標所在位置的一像素的圖像對象,通過其data屬性操作拿到它的像素值,也就是我們想得到的rgb值。

查看源碼

3.5 放大鏡

 實際上drawImage方法可以有多個參數,提供更加豐富的功能:

1  ctx.drawImage(image, dx, dy);
2  ctx.drawImage(image, dx, dy, dWidth, dHeight);
3  ctx.drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);

各個參數就像下面的示意圖這樣:

然后我們就可以使用drawImage方法在原圖像變換到繪制的圖像中做一個等比放大的操作,就可以實現放大鏡的效果啦。

查看源碼

3.6圖像的高斯模糊

其實,css中有一個兼容性不那么好的filter屬性,可以簡單的實現圖像模糊的效果:

 -webkit-filter: blur(20px); /* Chrome, Opera */
    -moz-filter: blur(20px);
     -ms-filter: blur(20px);    
         filter: blur(20px);

查看源碼

但是使用canvas可以實現真正意義上的高斯模糊(就是算法那種balabala的)。

這里有一個實現的很好的高斯模糊的js:「StackBlur

使用它我們就可以輕松的實現圖像的高斯模糊了:「查看源碼

 

文章中的源碼Demo都放在了github上,打開可能會有些慢,如果第一次打不開,刷新一下也會好了。 

四.資源

canvas中繪圖環境所有的屬性和方法都可以在這里找到:「CanvasRenderingContext2D interface

使用CSS將圖片轉換成模糊(毛玻璃)效果」

Canvas API

javascript標准參考教程Canvas


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM