目錄:
創建canvas。
繪制直線、多邊形和七巧板。
繪制弧和圓。
(有些圖過於寬,被擠壓了。可以去相冊【canvas用到的圖。】看原圖。)
HTML5的新標簽<canvas></canvas>
在使用時會添加id,通過id來獲取canvas元素來進行繪圖操作。
<canvas id="canvas"></canvas>
可以添加樣式。在不指定寬高的時候,默認是300px*150px。
<canvas id="canvas" style="border:1px solid #aaa;display:block;margin:50px auto;"></canvas>
指定canvas大小是通過canvas標簽的width屬性和height屬性,而不是通過CSS指定,並且指定時是沒有單位的。
<canvas id="canvas" width="1024" height="768"></canvas>
使用JavaScript來獲取canvas,通過getContext得到繪圖的上下文環境。
var canvas = document.getElementById('canvas'); var context = canvas.getContext('2d'); //使用context進行繪制
除了在標簽內指定canvas的大小,還可以在JS中指定。
canvas.width=1024; canvas.height=768;
當浏覽器不支持canvas時,可以使用以下兩種方法。
<canvas>當前浏覽器不支持canvas,請更換浏覽器後再試。</canvas>
(當浏覽器支持canvas時,canvas標簽的內容會被浏覽器忽略)
或者
var canvas = document.getElementById("canvas"); if(canvas.getContext("2d")){ var context = canvas.getContext("2d"); }else{ alert("當前浏覽器不支持canvas,請更換浏覽器後再試。") }
使用到的內容:
canvas.width
canvas.height
canvas.getContext()
context.moveTo(100,100); context.lineTo(200,200); context.stroke();
這三行代碼就可以實現繪制一條直線。
moveTo,相當於把筆觸放在坐標為100,100的位置。lineTo,就是從100,100畫到200,200的位置。此時直線還沒繪制出來,使用了context.stroke()方法才繪制出來。(這裡的坐標是相對於<canvas>來說的。<canvas>的左上角為坐標原點。)
moveTo和lineTo都是繪制狀態設置,而stroke()則是繪制。
除了moveTo,lineTo這兩個狀態設置。還有:
lineWidth。線條的寬度。
strokeStyle。線條樣式(顏色),字符串的格式。
context.lineWidth = 5; context.strokeStyle = 'blue';
先寫狀態再寫繪制。
繪制多條線段。只需要接上lineTo()就可以。
context.lineTo(100,200);
當最後的lineTo()的坐標和moveTo()的坐標一致,就可以實現首尾銜接的多邊形。
context.lineTo(100,100);
矩形,梯形,五星形等的畫法同理。
stroke()主要是繪制線條。
對多邊形進行著色,狀態:fillStyle,繪制方法:fill()
context.fillStyle = 'rgb(30,60,90)'; context.fill();
繪制路徑並且著色:
var canvas = document.getElementById('canvas'); canvas.width = 300; canvas.height = 300; var context = canvas.getContext('2d');
context.moveTo(100,100); context.lineTo(200,200); context.lineTo(100,200); context.lineTo(100,100); context.fillStyle = 'rgb(30,60,90)'; context.fill(); context.lineWidth = 5; context.strokeStyle = 'blue'; context.stroke();
當畫第二個線段/多邊形的時候,只需要重新調用moveTo()。
context.moveTo(200,100); context.lineTo(250,250); context.strokeStyle = 'red'; context.stroke();
問題:為什麼兩條線條顏色,粗細一樣?
答案:canvas的繪制是基於狀態的,在調用第二個線段的stroke()方法時,第一個線段的狀態依然起作用,(既繪制了三角形又繪制了第二條線段),而第二個線段的strokeStyle覆蓋了第一個線段的strokeStyle。
把兩個線段的狀態分開,方法:beginPath(),在定義路徑前調用(moveTo()之前)。相應的,在路徑定義完後,使用closePath()。
使用到的內容:
context.moveTo(x1,y1)
context.lineTo(x2,y2)
context.beginPath()
context.closePath()
context.lineWidth
context.strokeStyle
context.fillStyle
context.stroke()
context.fill()
繪制七巧板。
<canvas id="canvas" style="border:1px solid #aaa;display: block;margin: 50px auto;"> 當前浏覽器不支持canvas,請更換浏覽器後再試。 </canvas>
var tangram = [ {p:[{x:0,y:0},{x:800,y:0},{x:400,y:400}],color:'red'}, {p:[{x:0,y:0},{x:400,y:400},{x:0,y:800}],color:'orange'}, {p:[{x:800,y:0},{x:800,y:400},{x:600,y:600},{x:600,y:200}],color:'yellow'}, {p:[{x:600,y:200},{x:600,y:600},{x:400,y:400}],color:'green'}, {p:[{x:400,y:400},{x:600,y:600},{x:400,y:800},{x:200,y:600}],color:'lightblue'}, {p:[{x:200,y:600},{x:400,y:800},{x:0,y:800}],color:'blue'}, {p:[{x:800,y:400},{x:800,y:800},{x:400,y:800}],color:'purple'} ] window.onload = function(){ var canvas = document.getElementById('canvas'); canvas.width = 800; canvas.height = 800; var context = canvas.getContext('2d'); for(var i=0;i<tangram.length;i++){ draw(tangram[i],context); } } function draw( piece , ctx ){ ctx.beginPath(); ctx.moveTo(piece.p[0].x,piece.p[0].y); for(var i=1;i<piece.p.length;i++){ ctx.lineTo(piece.p[i].x,piece.p[i].y); } ctx.closePath(); ctx.fillStyle = piece.color; ctx.fill(); ctx.strokeStyle = 'pink'; ctx.lineWidth = 3; ctx.stroke(); }
context.arc(x,y,radius,startingAngle,endingAngle,anticlockwise=false)
繪制弧線。參數分別是,圓心的坐標x,y,圓的半徑radius,開始的弧度值,結束的弧度值,順時針轉動/逆時針轉動(false代表順時針轉動,true代表逆時針轉動)。
弧度/角度。
無論順時針/逆時針,弧度是不變的。
以下是順時針的角度。
畫3/4個圓。arc()也是狀態設置。最後一個參數不填時,默認false,即順時針。
context.lineWidth = 5; context.strokeStyle= 'blue'; context.arc(150,150,100,0,1.5*Math.PI); //圓心(150,150),半徑100,從0弧度到1.5PI弧度。 context.stroke();
將最後一個參數設置為true時。
context.arc(150,150,100,0,1.5*Math.PI,true);
繪制多段弧。
context.lineWidth = 5; context.strokeStyle= 'blue'; for(var i=0;i<10;i++){ context.beginPath(); context.arc(50+i*100,60,40,0,2*Math.PI*(i+1)/10); context.closePath(); context.stroke(); }
問題:為什麼弧的開始開始和結尾處被一條直線連接起來了?
答案:這是closePath()的另一個作用。當當前繪制的路徑不是封閉路徑時,使用了closePath()的話,就會自動將這段不封閉的路徑在首尾處使用一條線連接。
以上代碼不使用closePath()就不會首尾相連:
使用closePath(),並且逆時針方向繪制:
不使用closePath(),並且逆時針方向繪制:
填充處理。strokeStyle改為fillStyle。stroke()改為fill()。並且closePath()的效果:
去掉closePath():
注意:closePath()對於fill()來說是不起作用的。當調用fill()時,無論你是否調用closePath(),會自動將不封閉的內容首尾相連再填充。
使用到的內容:
context.arc(x,y,radius,startingAngle,endingAngle,anticlockwise=false)