HTML5- Canvas入門(七)

這是本系列的最後一篇入門文章,主要是對剩餘的未說明的canvas方法來逐個介紹。javascript

首先,若是你是一名擅長矢量設計的設計師,對Illustrator或者Fireworks很熟悉的話,那你確定知道它們有一個很強大的矢量混合處理功能,能夠對多個矢量路徑進行「合併」、「拆分」、「結合」、「相交」等系列操做。 以下圖,在Fireworks中有三個矢量路徑,我先把灰色的圓形和粉紅色的矩形進行了「結合路徑」的處理,接着又把結合後的路徑跟綠色的星形矢量進行了「合併路徑」操做:html

在canvas中也有實現一樣功能的屬性—— globalCompositeOperation,利用它,能夠實現對畫布上已有的圖像(暫稱爲「目標圖像」)和新繪製的圖像(暫成爲「源圖像」)來執行相關的混合處理。java

globalCompositeOperation的可取值見下表:git

描述
source-over 默認。在目標圖像上顯示源圖像。
source-atop 在目標圖像頂部顯示源圖像。源圖像位於目標圖像以外的部分是不可見的。
source-in 在目標圖像中顯示源圖像。只有目標圖像內的源圖像部分會顯示,目標圖像是透明的。
source-out 在目標圖像以外顯示源圖像。只會顯示目標圖像以外源圖像部分,目標圖像是透明的。
destination-over 在源圖像上方顯示目標圖像。
destination-atop 在源圖像頂部顯示目標圖像。源圖像以外的目標圖像部分不會被顯示。
destination-in 在源圖像中顯示目標圖像。只有源圖像內的目標圖像部分會被顯示,源圖像是透明的。
destination-out 在源圖像外顯示目標圖像。只有源圖像外的目標圖像部分會被顯示,源圖像是透明的。
lighter 顯示源圖像 + 目標圖像。
copy 顯示源圖像。忽略目標圖像。
xor 使用異或操做,對源圖像與目標圖像進行結合處理。

咱們繪製一個藍色的圓形和一個粉紅色的矩形,對它們進行相似上圖「結合路徑」(xor)的處理:github

<canvas id="myCanvas" width="300" height="200" style="border:solid 1px #CCC;">
您的瀏覽器不支持canvas,建議使用最新版的Chrome
</canvas>

<script type="text/javascript">
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d"); 
ctx.arc( 80, 80, 40, 0, 2*Math.PI);
ctx.fillStyle = "#4DA6FF";
ctx.fill();
ctx.fillStyle = "#FF7373";
ctx.globalCompositeOperation="xor";  //異或結合處理
ctx.fillRect(95,50,100,90);
</script>

效果以下:
web

各globalCompositeOperation 屬性值的最終效果能夠參考下圖(藍色矩形爲目標圖像,紅色圓形爲後續新繪製的源圖像):canvas

接着介紹 isPointInPath() 方法,它接受一個指定點的座標值做爲參數,可判斷該指定點是否位於當前路徑內,並返回對應的Boolean值。
咱們來繪製一個矩形,而後判斷點(115, 70)是否位於該矩形路徑內部,若是是,則填充該矩形,不然alert出相關信息:後端

<script type="text/javascript">
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.rect(95,50,100,90);
if (ctx.isPointInPath(115,70)){  //判斷點(115,70)是否位於當前路徑內
    ctx.fillStyle = "#FF7373";
    ctx.fill();
}else{
    alert("不在矩形路徑內");
}
</script>

因爲該點是位於矩形路徑上的,故成功繪製矩形,而不會彈窗:api

 咱們常規使用canvas繪製多個圖片的時候,總有一些會重複使用到的狀態,好比咱們先繪製了一個「傾斜20度、填充顏色爲紅色」的矩形,接着繪製了一個「不傾斜、填充顏色爲藍色」的矩形。若是後面咱們又要重複繪製一個「傾斜20度、填充顏色爲紅色」的矩形,又得從新設置畫布的setTransform和fillStyle值,天然是挺煩人的事情。
canvas的 save() restore() 方法便能爲咱們處理這個問題——使用 .save() 方法能爲咱們保存當前畫布的狀態,使用 .restore() 方法能夠把當前畫布狀態返回到上一次保存的狀態,有點相似於咱們玩遊戲過程當中存檔和讀檔的功能。
咱們先說說canvas的「狀態」,它指的是像咱們上面提到的「傾斜(變形)、填充」這樣的配置,是當前全部樣式和變形的一個快照。咱們能夠保存和讀取到的狀態包括:瀏覽器

當前的 transformation matrix;
當前的 clipping region;
當前的屬性值:fillStyle, font, globalAlpha,
globalCompositeOperation, lineCap, lineJoin,
lineWidth, miterLimit, shadowBlur, shadowColor,
shadowOffsetX, shadowOffsetY, strokeStyle, textAlign,
textBaseline

canvas的狀態是以棧(stack)的方式保存的,遵循先進後出(FILO)原則。每一次調用 save 方法,當前的狀態就會被推入棧中保存起來;當調用 restore 方法時,最新入棧的狀態則被推出使用。
咱們來一個簡單的例子:

<canvas id="myCanvas" width="150" height="150" style="border:solid 1px #CCC;">
您的瀏覽器不支持canvas,建議使用最新版的Chrome
</canvas>

<script type="text/javascript">
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.fillStyle = "green";
ctx.fillRect(20,20,100,100);
ctx.save();  //保存狀態(fillStyle = "green")
ctx.fillStyle = "red";
ctx.fillRect(40,40,60,60);
ctx.restore();  //讀取上次保存的狀態(fillStyle = "green")
ctx.fillRect(60,60,20,20);   //填充了綠色的矩形而非紅色的
</script>

效果以下:

上面的例子很好理解,不過爲了瞭解「狀態入棧出棧」的狀況,咱們把上面例子改造一下:

<canvas id="myCanvas" width="150" height="150" style="border:solid 1px #CCC;">
您的瀏覽器不支持canvas,建議使用最新版的Chrome
</canvas>

<script type="text/javascript">
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.fillStyle = "yellow";  //注意這裏多了一行狀態定義
ctx.save();    //注意這裏多了一行狀態保存
ctx.fillStyle = "green";
ctx.fillRect(20,20,100,100);
ctx.save();
ctx.fillStyle = "red";
ctx.fillRect(40,40,60,60);
ctx.restore();   //推出最後一個入棧的狀態(fillStyle = "green")
ctx.restore();   //再次推出最後一個入棧的狀態(fillStyle = "yellow"),注意green已經在上次restore推出了,故此次取到的是yellow
ctx.fillRect(60,60,20,20);  //填充黃色的矩形
</script>

就像註釋說明的那樣,最終繪製的小矩形是黃色而非綠色:

最後介紹的是 toDataURL() 方法,它能把當前畫布的內容轉換爲data類型的URL格式。 等等,「data類型的URL格式」又是什麼來的? 有時候咱們會在某些頁面(好比github404頁面)看到這樣的圖片:

其src對應的是一串「data:image/png;base64....」的data類型URL格式,返回的base64圖片數據流,能夠減小對服務器的圖片請求(固然缺點是沒法緩存在客戶端)。這種格式這就是咱們上面提到的東西。 那麼 toDataURL() 方法的好處就顯而易見了——咱們能夠把當前畫布內容轉換爲一張圖片。

toDataURL() 方法直接做用於canvas對象,而非context2D對象,其格式爲:

url = canvas.toDataURL( [ type, ... ] )

參數type表示返回文件的MINE類型,若未指定type,則默認返回的格式必須爲PNG格式。若是canvas沒有任何像素,則返回值爲:「data:,」,這是最短的data:URL,在text/plain資源中表現爲空字符串。
type的值能夠在image/png,image/jpeg,image/svg+xml 等MIME類型中選擇。若是是image/jpeg,能夠有第二個參數,若是第二個參數的值在0-1之間,則表示JPEG的質量等級,不然使用瀏覽器內置默認質量等級。

咱們來個小例子:

<canvas id="myCanvas" width="150" height="150" style="border:solid 1px #CCC;"></canvas>

<button onClick="openImg()">點我查看圖片</button>

<script type="text/javascript">
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.fillStyle = "green";
ctx.fillRect(20,20,100,100);
ctx.save();
ctx.fillStyle = "red";
ctx.fillRect(40,40,60,60);
ctx.restore(); 
ctx.fillRect(60,60,20,20); 

function openImg(){
    var image = c.toDataURL("image/png"),  //注意toDataURL是canvas對象方法,而不是context2D的屬性
         w  = window.open('about:blank'); 
    w.document.write("<img src='"+image+"' />"); 
}
</script>

點擊「點我查看圖片」的按鈕後會彈出一個新頁面,上面有咱們生成的base64編碼形式的圖片(跟canvas上繪製的內容一致):

但因爲該圖片是不存在於任何文件目錄上的,天然也沒法直接下載該(帶後綴名的)文件,若是想要地道地生成一張圖片供用戶下載,則須要後端配合了(能夠參考這裏)。
另外有一點要注意的,也就是咱們在第五章提到的,若是在canvas中繪製了非本地的圖片,從安全性考慮將沒法對其進行讀操做,這種狀況下若是執行toDataURL天然也會報錯。不過若是資源開啓了CORS,則有辦法避開同源策略的阻攔(能夠參考這裏)。

自此,canvas的api咱們基本都遍歷了一遍,但願能讓來此學習的朋友有所收穫,共勉~

相關文章
相關標籤/搜索