參考博文:
Html5 canvas畫圖教程17:論beginPath的重要性
先看兩個例子
例1:
<canvas id="myCanvas" width="300" height="300" style="border:1px solid #000000;">
您的瀏覽器不支持 HTML5 canvas 標簽。
</canvas>
<script>
var ctx = document.getElementById("myCanvas").getContext('2d');
ctx.beginPath();
ctx.moveTo(100.5,20.5);
ctx.lineTo(200.5,20.5);
ctx.strokeStyle = 'black';//默認strokeStyle='black', lineWidth=1, 此處可省略
ctx.stroke();
ctx.beginPath();
ctx.moveTo(100.5,40.5);
ctx.lineTo(200.5,40.5)
ctx.strokeStyle = 'red';
ctx.stroke();
</script>
結果:
例2:去掉第2個beginPath()
<canvas id="myCanvas" width="300" height="300" style="border:1px solid #000000;">
您的瀏覽器不支持 HTML5 canvas 標簽。
</canvas>
<script>
var ctx = document.getElementById("myCanvas").getContext('2d');
ctx.beginPath();
ctx.moveTo(100.5,20.5);//①
ctx.lineTo(200.5,20.5);//②
ctx.strokeStyle = 'black';//默認strokeStyle='black', lineWidth=1, 此處可省略
ctx.stroke();
ctx.moveTo(100.5,40.5);//③
ctx.lineTo(200.5,40.5)//④
ctx.strokeStyle = 'red';
ctx.stroke();
</script>
結果:
1. beginPath
- canvas中的繪制方法(如stroke, fill),都會以“上一次beginPath”之后的所有路徑為基礎進行繪制。比如例2中stroke了兩次,都是以第一次beginPath后的所有路徑為基礎畫的。
- 第一次stroke:畫①②,黑色
- 第二次stroke:畫①②③④,紅色(其中①②紅色覆蓋之前的黑色)
- 不管你用moveTo把畫筆移動到哪里,只要不beginPath,那你一直都是在畫一條路徑(注:此處『一條路徑』並非指連在一起)
- fillRect與strokeRect這種直接畫出獨立區域的函數,也不會打斷當前的path.
2. closePath
- closePath的意思不是結束路徑,而是關閉路徑,它會試圖從當前路徑的終點連一條路徑到起點,讓整個路徑閉合起來。但是,這並不意味着它之后的路徑就是新路徑了
- 與beginPath幾乎沒有關系:不要企圖通過閉合現有路徑來開始一條新路徑,而開始一條新路徑,以前的路徑也不會閉合。
對於繪制多段弧,看下面幾個例子:
例3:
var context = document.getElementById("myCanvas").getContext('2d');
context.strokeStyle="#005588";
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();
}
結果:
例4:在例3的基礎上只去掉closePath()
var context = document.getElementById("myCanvas").getContext('2d');
context.strokeStyle="#005588";
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();
}
結果:
例5:在例3的基礎上去掉beginPath()和closePath()
var context = document.getElementById("myCanvas").getContext('2d');
context.strokeStyle="#005588";
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();
}
結果:
可見,在這種情況下,每個弧畫完都會連到下一個弧的起點
例6:在例3的基礎上只去掉beginPath()
var context = document.getElementById("myCanvas").getContext('2d');
context.strokeStyle="#005588";
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();
}
結果:
這樣看不太清晰,我們將i < 10
改為i < 3
,只顯示前三個:
可見,在這種情況下,每個弧畫完都會先回到第一個弧的起點,然后再連到下一個弧的起點
例7:在例3的基礎上將stroke()改為fill()
var context = document.getElementById("myCanvas").getContext('2d');
context.fillStyle="#005588";
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.fill();
}
結果:
例8:在例7的基礎上去掉closePath()
var context = document.getElementById("myCanvas").getContext('2d');
context.fillStyle="#005588";
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.fill();
}
結果:
比較例7和例8可知:
無論是否closePath(),結果都一樣。
因為closePath()對於fill()是沒有用的:無論是否closePath(),調用fill()時,canvas會自動把沒有封閉的路徑首尾相連,之后進行填充