周老虎落網的時候,網易跟騰訊都推出了牛逼轟轟的HTML5頁面來展現其關係網(網易http://news.163.com/special/data_zyk/ ,騰訊http://news.qq.com/zt2014/zykgxw/index.htm),查看這倆頁面,都是經過H5中canvas強大的繪圖功能來實現的。若是你不曾學習過H5,看完這倆屌炸天的頁面,興許會勾起你學習的慾望。css
canvas其實沒有那麼玄乎,它不外乎是一個H5的標籤,跟其它HTML標籤一模一樣:css3
<canvas></canvas>
canvas自己沒有任何的繪圖能力,全部的繪圖工做都是經過js來實現的。一般咱們在js經過getElementById來獲取要操做的canvas(這意味着咱得給canvas設個id):canvas
<canvas id="myCanvas"></canvas> <script> var c = document.getElementById("myCanvas"); //獲取要操做的canvas //操做canvas的代碼... </script>
注意最好在一開始的時候就給canvas設置好其寬高(若不設定寬高,瀏覽器會默認設置canvas大小爲寬300、高100像素),並且不能使用css來設置(會被拉伸),建議直接寫於canvas標籤內部:瀏覽器
<canvas id="myCanvas" width="200" height="200"></canvas>
也能夠在js腳本中設置:ide
<canvas id="myCanvas"></canvas> <script> var c = document.getElementById("myCanvas"); c.width=200; c.height=200; </script>
關於canvas大小須要知道的一點是,後續我們對canvas所作的所有繪圖操做,超出此大小範圍的部分是不可見的。顧名思義,能夠把canvas當作一塊畫布,其大小是咱設定好的寬高,那麼不管你怎麼畫,畫布外的地方天然是畫不到的。函數
對於有些瀏覽器是不支持canvas功能的,咱們能夠直接在canvas標籤中寫一些替換內容,在瀏覽器不支持canvas時顯示:學習
<canvas id="myCanvas" width="200" height="200" style="border:solid 1px #CCC;"> 您的瀏覽器不支持canvas,建議使用最新版的Chrome </canvas>
接着在聊如何在canvas上繪圖前,咱得先說說.getContext("2d")這東西。
.getContext() 是canvas的繪圖對象/方法,要讓canvas執行繪圖工做必須先獲取canvas的.getContext()對象來執行。spa
.getContext()只接受一個參數,該參數用於獲取canvas的繪圖環境,例如.getContext("2d")表示該canvas的繪圖環境爲2D平面(能夠繪製文本、直線、弧線、矩形、圓形等)。當前H5只支持2D環境,在不久的未來會開放3D繪圖功能。(故咱可將「getContext」翻譯爲「獲取繪圖環境」)翻譯
理論很少說,咱們先來個小例子,從最簡單的繪製直線開始:設計
<canvas id="myCanvas" width="200" height="200" style="border:solid 1px #CCC;"> 您的瀏覽器不支持canvas,建議使用最新版的Chrome </canvas> <script> var c = document.getElementById("myCanvas"); var ctx = c.getContext("2d"); //獲取該canvas的2D繪圖環境對象 ctx.moveTo(10,10); //定義繪畫開始的位置 ctx.lineTo(150,50); //畫一條直線,結束點座標是x=150,y=50 ctx.stroke(); //描邊 </script>
效果以下:
在這裏咱們使用了3個getContext("2d")對象的繪圖方法:
.moveTo(x座標 , y座標) 能夠理解爲定位畫筆在畫布上的位置(注意全部繪圖方法所定義的座標是相對canvas而言的而不是瀏覽器窗口,對canvas來講,最左上角的點的座標是(0,0))
.lineTo(x座標 , y座標) 顧名思義,就是畫一條直線到某個點,很好理解。須要知道的是此方法僅僅作路徑運動,而不存在任何視覺上的繪圖效果(上色、描邊)
.stroke() 描邊方法,有玩過AfterEffect的朋友會很清楚,不給運動路徑加stroke特效的畫是不存在描邊效果的,canvas也同樣,想要運動路徑軌跡能有視覺效果,須要使用相應的上色/描邊方法
自此咱們很輕鬆地繪製了一條黑色的直線,但若是咱們想要繪製一條紅色的或者其它顏色的線段,該怎麼作呢?
答案很簡單,使用ctx.strokeStyle來設定描邊的顏色便可。咱們畫三條紅色的線段吧:
<canvas id="myCanvas" width="200" height="200" style="border:solid 1px #CCC; margin:30px;"> 您的瀏覽器不支持canvas,建議使用最新版的Chrome </canvas> <script> var c = document.getElementById("myCanvas"); var ctx = c.getContext("2d"); //獲取該canvas的2D繪圖環境對象 ctx.moveTo(0,0); //咱把「畫筆」移到座標(0,0) ctx.lineTo(150,50); //從上個點(0,0)畫一條直線,結束點座標是(150,50) ctx.lineTo(20,100); //從上個點(150,50)繼續畫一條直線,結束點座標是(20,100) ctx.moveTo(90,90); //咱把「畫筆」移到座標(90,90) ctx.lineTo(80,150); //從上個點(60,60)繼續畫一條直線,結束點座標是(80,150) ctx.strokeStyle = "red"; //設定描邊顏色爲紅色,只要寫在.stroke()方法前面便可 ctx.stroke(); //描邊 </script>
註釋都說的很清楚了,故再也不贅述實現原理,其效果以下:
注意在開始繪製路徑的時候,必定要加上moveTo(x,y),不然第一個lineTo()的運動軌跡將不計入繪圖中(瀏覽器會認爲沒獲取到該運動軌跡的起始點,故忽略此線段)。
另外有一個問題,若是上方咱們會出來的兩條線段(嗯,一條折線,一條直線),咱們但願第一條折線是藍色的,第二條直線是紅色的,應當怎麼作?
你會地很天然地作以下處理:
<script> var c = document.getElementById("myCanvas"); var ctx = c.getContext("2d"); ctx.moveTo(0,0); ctx.lineTo(150,50); ctx.lineTo(20,100); ctx.strokeStyle = "blue"; //設定描邊顏色爲藍色 ctx.stroke(); ctx.moveTo(90,90); ctx.lineTo(80,150); ctx.strokeStyle = "red"; //設定描邊顏色爲紅色 ctx.stroke(); </script>
但運行腳本會發現,折線除了被描了一遍藍色,也被描了一遍紅色:
這是由於canvas在第二次給路徑上色時,是把以前的全部路徑軌跡合在一塊兒來上色的,除非我們讓canvas知道那折線和直線應該是獨立開來的倆路徑。
咱們可使用.beginPath()來解決:
<script> var c = document.getElementById("myCanvas"); var ctx = c.getContext("2d"); ctx.moveTo(0,0); ctx.lineTo(150,50); ctx.lineTo(20,100); ctx.strokeStyle = "blue"; //設定描邊顏色爲藍色 ctx.stroke(); ctx.beginPath(); //告訴canvas我們要從新繪製一條全新的路徑了,以前畫的東西今後再無關係 ctx.moveTo(90,90); ctx.lineTo(80,150); ctx.strokeStyle = "red"; //設定描邊顏色爲紅色 ctx.stroke(); </script>
有的朋友一開始會搞不清楚beginPath()的用途,以爲有moveTo()就能夠了,其實beginPath()能夠作到上述的隔離路徑繪製效果的做用,防止以前的效果被污染。
接着嘮嗑.strokeStyle的賦值方式,我們上方是直接用了 ctx.strokeStyle="red" 來定義描邊顏色爲紅色,不過ctx.strokeStyle可獲值的形式有三種:
ctx.strokeStyle=color|gradient|pattern; //即支持 「顏色/漸變/圖案筆刷」 的賦值
⑴ 先看看color賦值方式,和咱們常規的css賦值是同樣的,支持css3顏色值標準,以下例:
//下面四種形式都是同樣的,表示描邊顏色爲「橙色」 ctx.strokeStyle = "orange"; ctx.strokeStyle = "#FFA500"; //#rrggbb形式 ctx.strokeStyle = "rgb(255,165,0)"; //RGB形式 ctx.strokeStyle = "rgba(255,165,0,1)"; //比上面的rgb多了個a(Alpha),即透明度
⑵ 再看下漸變gradient,這個稍有複雜:
var c = document.getElementById("myCanvas"); var ctx = c.getContext("2d"); ctx.moveTo(0,0); ctx.lineTo(150,50); ctx.lineTo(20,100); var grd = ctx.createLinearGradient(0,0,170,0); //定義線性漸變對象,設定漸變線起始點和結束點座標,座標格式爲(起始點x,起始點y,結束點x,結束點y) grd.addColorStop(0,"black"); //定義漸變線起點顏色 grd.addColorStop(0.5,"red"); //定義漸變線中間點的顏色 grd.addColorStop(1,"yellow"); //定義漸變線結束點的顏色 ctx.strokeStyle = grd; //將漸變對象賦值給strokeStyle ctx.stroke(); //描邊
效果以下:
這裏咱們提到了一個概念叫「漸變線」,沒有玩過設計的朋友須要瞭解下漸變的知識點,咱們能夠把LinearGradient(線性漸變,另有放射狀/圓形漸變RadialGradient)範圍當作一個矩形(你能夠經過Illustator、Photoshop等專業設計軟件來輔助你理解這點):
咱們一開始定義線性漸變對象的代碼 var grd = ctx.createLinearGradient(0,0,170,0) 不外乎就是設定了線性漸變線起始點爲(0,0),結束點爲(170,0)。
緊接着咱們經過 addColorStop( 漸變線位置<0~1>, 顏色 ) 來設定了漸變色值,分別在漸變線0、0.五、1的位置設置了黑色、紅色、黃色,其漸變效果以下:
經過 ctx.strokeStyle = grd 將漸變賦值給描邊方法,最終描邊獲得了咱們想要的漸變效果。
⑶ 最後看看pattern描邊方式,strokeStyle之因此不叫strokeColor是由於它除了支持顏色描邊還支持圖案描邊(搞設計的朋友或許稱做筆觸描邊會更有feel)。
線性漸變描邊須要先createLinerGradient(xstart,ystart,xend,yend),那麼設置圖案描邊天然也要先新建一個canvasPattern對象:
createPattern(image, repetitionStyle)
其中參數 image 表明圖案對象,通常經過 document.createElement('img') 或者 new Image() ,再定義其src值來建立該對象。
而repetitionStyle參數很好理解,即圖案重複形式,其可選值有"repeat" 、"repeat-x"、"repeat-y" 和"no-repeat" (和css的background-repeat可選值同樣,不贅述)。
那咱們能夠試着這樣寫:
<body> <canvas id="myCanvas" width="200" height="200" style="border:solid 1px #CCC; margin:30px;"> 您的瀏覽器不支持canvas,建議使用最新版的Chrome </canvas> <script> var c = document.getElementById("myCanvas"); var ctx = c.getContext("2d"); pic = new Image(); //建立圖片對象,或者 pic = document.createElement('img') pic.src = "http://images.cnblogs.com/cnblogs_com/vajoy/558870/o_5.jpg"; //定義圖片的映射地址 var redTexture = ctx.createPattern(pic, "repeat"); //定義Pattern對象,設定填充圖案爲pic圖片,填充形式爲平鋪 ctx.strokeStyle = redTexture; //定義描邊樣式爲上一行設定的Pattern描邊 ctx.moveTo(80,10); ctx.lineTo(10,90); ctx.stroke(); </script>
只是在執行效果的時候會發現,執行十次有九次不是咱們預期的圖片填充效果,而是默認的黑色描邊效果,這是爲什麼?
緣由在於瀏覽器可能還未加載完圖片pic,就已經執行了ctx.stroke(),解決方法是讓ctx在圖片pic加載完畢以後纔開始執行繪圖:
<canvas id="myCanvas" width="200" height="200" style="border:solid 1px #CCC; margin:30px;"> 您的瀏覽器不支持canvas,建議使用最新版的Chrome </canvas> <script> var c = document.getElementById("myCanvas"); var ctx = c.getContext("2d"); pic = new Image(); //建立圖片對象,或者 pic = document.createElement('img') pic.src = "http://images.cnblogs.com/cnblogs_com/vajoy/558870/o_5.jpg"; pic.onload = patternFill; //在圖片加載完成時執行繪圖函數 function patternFill() { //定義繪圖函數 var redTexture = ctx.createPattern(pic, "repeat"); ctx.strokeStyle = redTexture; ctx.moveTo(80,10); ctx.lineTo(10,90); ctx.lineWidth = 8; //定義線段粗度爲8像素 ctx.stroke(); } </script>
效果以下:
注意這裏我還加了個 ctx.lineWidth = 8 來設定線段的粗度。
自此咱們學習了strokeStyle的三個賦值方式,也學習了上述的經過 ctx.lineWidth = lineWeight 的形式來給線段設定粗度。
最後我們再學習兩個很簡單的線段屬性 lineCap 和 lineJoin。
⑴ lineCap是設定線段端點的形狀(線帽),其值能夠是
butt 默認,即線條端點爲平直的邊緣 round 線條端點爲圓角線帽 square 爲線條端點添加正方形線帽 |
<canvas id="myCanvas" width="250" height="120" style="border:1px solid #DDD;"> </canvas> <script> var c=document.getElementById("myCanvas"); var ctx=c.getContext("2d"); ctx.lineWidth=10; ctx.beginPath(); ctx.lineCap="butt"; ctx.moveTo(20,10); ctx.lineTo(200,60); ctx.strokeStyle="red"; ctx.stroke(); ctx.beginPath(); ctx.lineCap="round"; ctx.moveTo(30,90); ctx.lineTo(200,40); ctx.strokeStyle="blue"; ctx.stroke(); ctx.beginPath(); ctx.lineCap="square"; ctx.moveTo(10,30); ctx.lineTo(200,80); ctx.strokeStyle="green"; ctx.stroke(); </script>
代碼效果以下:
光看此圖可能看不太出「butt」和"square"的區別,但懂得使用AI繪製矢量的同窗們應該比較瞭解:
⑵ lineJoin則是設定折線的交接處的外角類型,其值可爲:
miter 默認,折線交接處爲尖角 round 折線交接處爲圓角 bevel 折線交接處爲斜角 |
<canvas id="myCanvas" width="200" height="220" style="border:1px solid #DDD;"> </canvas> <script> var c=document.getElementById("myCanvas"); var ctx=c.getContext("2d"); ctx.lineWidth=13; ctx.lineJoin="bevel"; ctx.moveTo(20,20); ctx.lineTo(100,50); ctx.lineTo(20,80); ctx.strokeStyle="red"; ctx.stroke(); ctx.beginPath(); ctx.lineJoin="round"; ctx.moveTo(20,60); ctx.lineTo(100,90); ctx.lineTo(20,150); ctx.strokeStyle="green"; ctx.stroke(); ctx.beginPath(); ctx.lineJoin="miter"; ctx.moveTo(20,90); ctx.lineTo(100,150); ctx.lineTo(20,200); ctx.strokeStyle="blue"; ctx.stroke(); </script>
效果以下:
須要瞭解的是,miter還受到了屬性miterLimit的影響(點此查看詳細),但我的以爲它跟bevel實現的效果是一致的,故在此不作介紹。
開篇就先講到這裏,主要是對canvas線段繪製功能的介紹,共勉~