在沒學canvas的時候,覺得canvas是這麼的神秘,這麼的絢麗,這麼的高深,用canvas做出來的效果是如此的炫酷,能做的事情如此的寬廣,簡直讓我心生敬畏之心,時常感歎:我要是得此技能,必定要上天了(注意,這裡不是要升天啊),那時候一直不敢涉獵的原因主要是,第一,在還需要兼容IE的時代,兼容性是硬傷;第二,參考資料的如此的少,又或是參考資料五花八門,沒有適合入門的比較好的參考文章,第三,canvas之所以能無所不能,其最大的原因是有一個好伙伴JavaScript,那是的JavaScript還是不甚了解。(借口真多)現在好了,終於有時間,有精力來研究研究這神秘莫測的canvas,考慮到現在適合入門的canvas基礎知識點的文字少之又少,於是,決定在接下來的一段時間裡,將canvas的API梳理一遍,畢竟工欲善其事,必先利其器嘛,廢話不多說,咱們就開始吧!
注:以下API中的各個屬性和方法都是目前支持的,不完全支持的就沒有介紹了!
初識canvas
要學習canvas,必先知道canvas為何物?
<canvas></canvas>
首先canvas只是html5中的一個便簽而已,表示的意思是一個畫布,它本身沒有任何作用,就相當於是一個畫板,你可以在它上面畫任何你想畫的東西,那如果我們不給它設置任何的屬性和樣式,它的默認狀態是什麼呢?運行上面的代碼可得如下:
默認的寬度為300px,高度為150px,當body背景為白色時,它的背景為白色,body背景為灰色時,它的背景為灰色,可知它的默認背景為透明色
<canvas></canvas> <span>你是什麼類型的標簽?</span>
在它後面加一個內聯樣式的標簽,看看它是什麼類型的標簽
span到它的右側去了,說明它是一個行內元素,好了,基本情況我們算了解了,那我們怎麼修改它的默認樣式呢?
首先,canvas作為一個html5比較特殊的標簽,也是支持樣式控制的,比如設置邊框,邊距,背景等等,但是有一個地方值得注意的是,在設置canvas寬高時,如果用style樣式來設置的話,會出現一點小問題,具體什麼問題,暫且賣個關子,後面為大家介紹,所以寬高還是在標簽上設置比較好
<canvas width="400" height="400" id="canvas"></canvas>
當然,canvas目前只是一個畫板而已,沒有畫筆,你什麼也做不了,那畫筆是什麼呢,這裡就是我們主角的開始了
var canvas = document.getElementById("canvas"); var ctx = canvas.getContext("2d"); //目前只有2d,沒有3d,以後會有的,如果想了解3d,可以看一下webGL
getContext("2d")是canvas的繪圖環境,只有引入它才能進行繪圖
有時我在想,canvas繪圖都是在js裡面完成的,那麼它本身的標簽能不能寫東西呢,比如,如果在它裡面放一張圖片,嘻嘻,會怎麼樣,那我們說干就干
<canvas width="400" height="400" id="canvas"> <img src="1.jpg" width="400" height="400" alt=""> </canvas>
當當當當,見證奇跡!馬丹,標准浏覽器下,什麼都沒有,看看不爭氣的IE,亮瞎眼,活脫脫一個大美女出現了
由此可見,在支持canvas的浏覽器,canvas裡面的東西是不會顯示的,但是在不支持的情況下,會赤裸裸的顯示出來,於是,我們可以把它作為提示用語,用來告訴不支持的浏覽器,該換換了
<canvas width="400" height="400" id="canvas"> <span>親,您的浏覽器不支持canvas,換個浏覽器試試吧!</span> </canvas>
恩,對於IE家族的低版本成員,年紀太大,只能這麼處理了,如果你非要支持IE,可以試試explorercanvas開源項目,裡面有一個excanvas.js,當然,在使用的時候注明是在ie下引用,地址我就沒給了,我也沒打算去研究它,因為我斷定,不久的將來,IE8以下浏覽器就不見了,呵呵,但願它快點到來!
前面都是聊騷,正在的主角才剛開始,任務艱巨,任重而道遠啊,canvas API分為屬性部分和方法部分,但是我不想這麼來講,這樣太機械了,看不懂的人依舊是看不懂,接下來的API我會采用相關屬性,方法交叉講解,再輔以小實例,相信這樣更讓人看得懂,而且會印象深刻,想想還有點小激動呢,API較長,只能分幾期來講了!
由於canvas默認背景為透明色,為區別畫布與body,以後的畫布樣式統一設置為如下:
body{ background:#ccc;} canvas{ background:#fff;}
畫畫嘛,都是從點,線,圓,框開始的,那我們就從點開始吧!
MoveTo(x,y) 顧名思義,就是移動到某個坐標點上,x,y 分別表示x軸坐標和y軸坐標
var canvas = document.getElementById("canvas"); var ctx = canvas.getContext("2d"); ctx.moveTo(100,100);
當然是不會有任何的效果的,因為這裡的意思就相當於把筆移動了100,100的位置,還沒有下筆呢,這並不是然並卵,這個是畫筆作畫的起點,比如畫直線,2點一線,只需再做一點就可以畫直線了
lineTo(x,y) 意思是連接最後一點的坐標,但是不畫,x,y 分別表示x軸坐標和y軸坐標
var canvas = document.getElementById("canvas"); var ctx = canvas.getContext("2d"); ctx.moveTo(100,100); ctx.lineTo(200,200);
然而並沒有任何效果,這是為什麼呢,實際上,上面只是標注了直線的起點和終點,還沒添墨水呢,何為墨水呢?
下面就來介紹我們的黑白雙煞:
fill() 填充,此為實心的
stroke() 繪制,此為空心的
因為線條的寬度只有一個像素,所以無法進行填充,於是畫線段用fill()方法是沒有用的,
var canvas = document.getElementById("canvas"); var ctx = canvas.getContext("2d"); ctx.moveTo(100,100); ctx.lineTo(200,200); ctx.stroke();
結果:
此黑白雙煞在以後的繪圖中起到核心作用,切記這2個方法(為什麼我叫它們黑白雙煞呢,因為canvas默認顏色為黑色,fill()填充顏色為一坨黑,stroke()繪制就像描邊一樣,一個框,裡面是透明的,由此得名,哈哈,方便記憶)。
點,線之後便是面了,我們來繪制矩形吧,矩形也有三兄弟,暫且命名為阮氏三兄弟:
rect(x,y,w,h) 在x,y坐標點繪制一個矩形,寬高為w,h,此方法只是繪制路徑,必須用黑白雙煞才能顯示
fillRect(x,y,w,h) 在x,y坐標點繪制一個填充矩形,寬高為w,h
strokeRect(x,y,w,h) 在x,y坐標點繪制一個描邊矩形,寬高為w,h
分別看看它們的表現
//不用黑白雙煞 var canvas = document.getElementById("canvas"); var ctx = canvas.getContext("2d"); ctx.rect(5.5,5.5,100,100);
//用stroke
var canvas = document.getElementById("canvas"); var ctx = canvas.getContext("2d"); ctx.rect(5.5,5.5,100,100) ctx.stroke();
//用fill var canvas = document.getElementById("canvas"); var ctx = canvas.getContext("2d"); ctx.rect(5.5,5.5,100,100) ctx.fill();
//用strokeRect var canvas = document.getElementById("canvas"); var ctx = canvas.getContext("2d"); ctx.strokeRect(5.5,5.5,100,100);
//用fillRect var canvas = document.getElementById("canvas"); var ctx = canvas.getContext("2d"); ctx.fillRect(5.5,5.5,100,100);
為了便於演示,我將畫布縮小到(120*120),以上為各個組合的表現,從這些表現可以總結一下幾點:
1、rect()不能單獨使用,必須借助fill(),stroke()方法;
2、rect()+stroke() 組合的效果和strokeRect()一致,可等價
3、rect()+fill() 組合的效果和fillRect()一致,可等價
這裡還有一個小細節需要注意的是,我這個的坐標寫的是5.5而不是6或5,為什麼?理論上繪制的線框是一個1像素的寬度的,因為一個點就是一像素,當坐標設為(6,6)時,表現會是如下:
對比上圖明顯粗一些,明顯是2個像素的寬度,這是為什麼呢?給大家畫一個圖
這3條線分別是5像素,6像素,7像素位置,圖形繪制時,繪制6像素的地方向左繪制0.5像素,向右繪制0.5像素,但是浏覽器實際上是不純在半個像素的,所以浏覽器會幫我們補上個半個像素,就成了2個像素了,如果要做成1像素邊框,只需將坐標左移或右移半個像素,即0.5px,如果要精確繪圖,須知這一點細節!
矩形之後就可以畫圓了,但是圓相對來說比較復雜,咱們還是先來練練字,謝謝書法,哈哈,看看canvas編輯文字有哪些方法:
我們說畫布上的圖形皆為路徑,所以,文字作為另一種圖形,也存在黑白雙煞:
fillText(text,x,y,[maxWidth]); 顧名思義,這是填充文字
strokeText(text,x,y,[maxWidth]); 顧名思義,這是描邊文字
參數:
text :需要繪制的文字
x,y: 文字繪制的起始坐標
[maxWidth] : 文字的最大寬度,選填
//為省篇幅,我合起來寫了,你想看到各自的效果,請分開運行 var canvas = document.getElementById("canvas"); var ctx = canvas.getContext("2d"); ctx.fillText('你想對我說什麼',50,50); ctx.strokeText('你想對我說什麼',50,50);
咋一看,你會說,咦,怎麼描邊文字看上去像是加粗的啊,為什麼會這樣呢?在此稍作懸念,下面揭曉!
我們看一下文字的默認表現:
var canvas = document.getElementById("canvas"); var ctx = canvas.getContext("2d"); ctx.fillText('你想對我說什麼',0,0);
結果簡直讓人大吃一精,哎,是驚!文字怎麼跑那裡去了,了解css 的都知道,文字是有基准線的,這玩意也是老外的英文搞出來的,html文字基准線是baseline,可以用vertical-align來修改基准線,canvas有嗎?哈哈,還真有:
textBaseline
參數:
alphabetic : 默認。文本基線是普通的字母基線。
top : 文本基線是 em 方框的頂端。
hanging : 文本基線是懸掛基線。
middle :文本基線是 em 方框的正中。
ideographic : 文本基線是表意基線。
bottom :文本基線是 em 方框的底端。
看著不懂?我也不太懂,文字不如圖片,看看這2張示意圖:
實際顯示:
//為了讓bottom看得到,我將文字向下偏移20像素 var canvas = document.getElementById("canvas"); var ctx = canvas.getContext("2d"); ctx.font="20px Arial"; ctx.textBaseline = "bottom"; ctx.fillText('你想對我說什麼',0,20);
圖沒有截對齊,湊合著看吧,哦,沒有在20px位置畫條線,算了,不糾結了,結合上面的圖看吧!
只要是文字,那就應該可以設置文字樣式,比如css中可以設置顏色,字體,字體大小,等等,css可不可以設置canvas樣式呢?咱們說干就干:
canvas{ background:#fff; font-family:"微軟雅黑"; font-size:20px; color:#f00; text-align:center;}
好像沒什麼反應,老年癡呆了?既然css無法設樣式,那怎麼給文字設置樣式呢?
還好強大的canvas自帶樣式設置技能,走哪裡都不怕,我們看看有哪些:
font 參數:font-style font-variant font-weight font-size font-family,分別表示的意思是字體樣式(如傾斜),是否大小寫,字體粗細,字體大小,字體
var canvas = document.getElementById("canvas"); var ctx = canvas.getContext("2d"); ctx.font="italic bold 40px 微軟雅黑 ";
ctx.textBaseline = "top"; ctx.fillStyle = 'red'; ctx.fillText('a你想對我說什麼',0,20);
這只是部分的font屬性,起用法與css相同,有興趣可以自己試一試。
textAlign 參數:left(默認,文本左對齊),right(文本右對齊),center(文本在指定位置居中),start(文本開始位置),end(文本結束位置)
這個其實也挺怪異的,如圖:
默認是左對齊,右對齊都跑出去了,center就只有一半,一般我們要想將文字居中對齊,其實不用center,而是通過坐標來居中,後面我會給一個文本上下左右居中的小實例供大家參考!
這裡說錯了,這裡的藍色的豎線是表示文本的開始水平位置,start與left效果相同,都是向左對齊,end和right效果相同,都是在起始點的左邊向右對齊,而center則是以這個點為中心點對齊!
字體顏色也跟黑白雙煞對應:
strokeStyle fillStyle
用法一樣,如:
strokeStyle = color 可設顏色
strokeStyle = gradient 可設漸變對象
strokeStyle = pattern 可創建 pattern 筆觸的 pattern 對象
現在可以揭曉上面的懸念了,我覺得實例更能說明問題:
var canvas = document.getElementById("canvas"); var ctx = canvas.getContext("2d"); ctx.font="40px Arial"; ctx.textBaseline = "top"; ctx.textAlign = 'left'; ctx.fillStyle = 'red'; ctx.fillText('你想對我說什麼',0,20); ctx.strokeStyle = 'green'; ctx.strokeText('你想對我說什麼',0,60);
效果:
如圖所示,描邊文字並不是加粗的,而是對文字進行描邊了,文字小時,就擠到一起了。
我們都知道,css3有一個新樣式 -- text-shadow,表示文字的陰影,canvas也有類似的功能,咱們就來對比一下吧!
shadowOffsetX 陰影距形狀的水平距離
shadowOffsetY 陰影距形狀的垂直距離
shadowBlur 陰影的模糊級別,這裡是高斯模糊,默認值為0
shadowColor 陰影的顏色
其實這個跟css3的陰影設置很相似,我就一起來看一下吧
html:
<canvas width="300" height="200" id="canvas"> <span>親,您的浏覽器不支持canvas,換個浏覽器試試吧!</span> </canvas> <span>你想對我說什麼</span>
css:
body{ background:#ccc;} canvas{ background:#fff;} span{ font-size:40px; font-family:Arial; color:red; text-shadow:5px 5px 5px #000; vertical-align: top; display:inline-block;}
js:
var canvas = document.getElementById("canvas"); var ctx = canvas.getContext("2d"); ctx.font="40px Arial"; ctx.textBaseline = "top"; ctx.textAlign = 'left'; ctx.fillStyle = 'red'; ctx.shadowOffsetX = 5; ctx.shadowOffsetY = 5; ctx.shadowBlur = 5; ctx.shadowColor = '#000'; ctx.fillText('你想對我說什麼',0,20); ctx.strokeStyle = 'green'; ctx.strokeText('你想對我說什麼',0,60);
效果:
看看,基本無差吧,但是還是有一點小區別的,如果給css3的text-shadow不設陰影顏色,它的陰影顏色會默認跟字體顏色一樣,但是如果如果不設shadowColor ;則陰影是出不來的,不信?看下圖:
補充一點:
measureText(text) 返回文本的寬度,單位為像素,用法是:
measureText(text).width
注意:此方法只能獲取到寬度,不能獲取到高度,跟我們一般獲取寬高的方法有點不一樣,它可以在文本輸出前計算出其寬度,故如果想在文本輸出前知道其寬度,這個方法只好有用武之地
var canvas = document.getElementById("canvas"); var ctx = canvas.getContext("2d"); ctx.font="24px 微軟雅黑"; ctx.fillStyle = 'red'; var txt = "快告訴我們我自己有多寬"; var w = ctx.measureText(txt).width; ctx.fillText('你的寬度:'+w,0,50); ctx.fillText(txt,0,100);
好了,篇幅太長了,今天就介紹到這裡,不知道前面講的這些屬性和方法是否能看的懂,感覺實例還是太少了,等API講完了,在出一下理解性的小實例幫助大家理解,今天就先到這裡!