這是本系列的最後一篇入門文章,主要是對剩餘的未說明的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咱們基本都遍歷了一遍,但願能讓來此學習的朋友有所收穫,共勉~