HTML5- Canvas入門(一)

周老虎落網的時候,網易跟騰訊都推出了牛逼轟轟的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>
View Code

代碼效果以下:

光看此圖可能看不太出「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>
View Code

效果以下:

須要瞭解的是,miter還受到了屬性miterLimit的影響(點此查看詳細),但我的以爲它跟bevel實現的效果是一致的,故在此不作介紹。

開篇就先講到這裏,主要是對canvas線段繪製功能的介紹,共勉~

donate
相關文章
相關標籤/搜索