Canvas圖形繪制 <small>API參考</small>
- 開(kāi)始創(chuàng)建路徑
ctx.beginPath()
外构,通過(guò)此方法避免前面的圖形重復(fù)繪制普泡。 - (以圓形為例)創(chuàng)建圓形路徑
ctx.arc(x, y, radius, startAngle, endAngle, anticlockwise)
<small>- x:圓心X坐標(biāo);
- y:圓心Y坐標(biāo)审编;
- radius:圓半徑撼班;
- startAngle:起始弧度,一般為0垒酬;根據(jù)情況而定砰嘁;
-
endAngle:結(jié)束弧度,
2 * Math.PI
表示360°勘究; -
anticlockwise:可選值矮湘;默認(rèn)為false,即順時(shí)針繪制口糕;如果為 true缅阳,逆時(shí)針繪制圓弧。
</small>
- 關(guān)閉路徑
ctx.closePath()
:將筆點(diǎn)返回到當(dāng)前子路徑起始點(diǎn)的方法景描;它嘗試從當(dāng)前點(diǎn)到起始點(diǎn)繪制一條直線十办。 如果圖形已經(jīng)是封閉的或者只有一個(gè)點(diǎn),那么此方法不會(huì)做任何操作超棺。
<small>若不需要封閉非整圓橘洞,請(qǐng)勿使用該方法;否則會(huì)在非整圓終點(diǎn)至起始點(diǎn)繪制一條直線说搅。</small>
- 設(shè)置畫(huà)筆繪制樣式<small>(填充
ctx.fillStyle
;劃線ctx.strokeStyle
虏等,線寬ctx.lineWidth
弄唧。)</small> - 開(kāi)始繪制圖形<small>(填充
ctx.fill()
,劃線ctx.stroke()
)</small>
<!--canvas arc demo-->
<script>
"use strict"
window.onload = function() {
var canvas = document.getElementById("canvas");
if (canvas == null) {
return false;
}
// 獲得一個(gè)2d渲染上下文
var ctx = canvas.getContext("2d");
for (var i = 1; i < 10; i++) {
// 創(chuàng)建路徑霍衫;如果不重新創(chuàng)建路徑候引,存在的圖形路徑會(huì)重復(fù)繪制
ctx.beginPath();
//創(chuàng)建圖形路徑;
ctx.arc(50 * i, 50 * i, 20 * i, 0, 2 * Math.PI, true);
//閉合路徑;
ctx.closePath();
//設(shè)置填充顏色
ctx.fillStyle = "rgba(255,0,0,0.25)";
//開(kāi)始填充圖形
ctx.fill();
// 劃筆樣式
ctx.strokeStyle = "#ff0";
// 劃線渲染
ctx.stroke();
}
}
</script>
<canvas id="canvas" width="1000" height="1000"></canvas>
</body>
moveTo & lineTo & beginPath & closePath
- moveTo(x,y):將畫(huà)筆移動(dòng)到x,y坐標(biāo)(該坐標(biāo)為第一個(gè)子路徑的終點(diǎn))敦跌;
- lineTo(x,y):直線連接子路徑的終點(diǎn)到x澄干,y坐標(biāo)(只連接逛揩,不繪制);
- beginPath():通過(guò)清空子路徑列表開(kāi)始一個(gè)新路徑的方法麸俘。 當(dāng)你想創(chuàng)建一個(gè)新的路徑時(shí)辩稽,調(diào)用此方法;
- closePath():從當(dāng)前點(diǎn)到起始點(diǎn)繪制一條直線从媚。 如果圖形已經(jīng)是封閉的或者只有一個(gè)點(diǎn)逞泄,那么此方法不會(huì)做任何操作。
重點(diǎn):沒(méi)有子路徑時(shí)(即沒(méi)有moveTo或lineTo時(shí))拜效,lineTo作用與moveTo相同
代碼示例:
<body>
<script>
window.onload = function () {
var canvas = document.getElementById("canvas");
if (canvas == null) {
return false;
}
var context = canvas.getContext("2d");
//創(chuàng)建路徑
context.beginPath();
//移動(dòng)畫(huà)筆 1.將畫(huà)筆移動(dòng)到50喷众,50的坐標(biāo)
context.moveTo(50, 50);
//畫(huà)第一條線 2.從moveTo的50,50到lineTo的400,50坐標(biāo)劃一條線
context.lineTo(100, 50);
//畫(huà)第二條線 3.從上一個(gè)lineTo的400,50到這個(gè)lineTo的50,400坐標(biāo)劃一條線
context.lineTo(50, 100);
//從當(dāng)前點(diǎn)(50,400)到起始點(diǎn)(beginPath后moveTo的50,50)劃一條線
context.closePath();
//畫(huà)筆顏色
context.strokeStyle = "#ccc";
//線的寬度
context.lineWidth = "5";
//渲染,即開(kāi)始繪畫(huà)
context.stroke();
/*該例子中closePath()相當(dāng)于lineto(50,50);故這條線是50,50到100,100兩點(diǎn)的直線*/
context.lineTo(100, 100);
context.stroke();
/*清空路徑列表紧憾,重新創(chuàng)建一個(gè)新的路徑*/
context.beginPath();
/*當(dāng)前不存在子路徑到千,故此方法作用與moveTo(200,200)相同*/
context.lineTo(200, 200);
/*將200,200這個(gè)子路徑終點(diǎn)連接到250,250*/
context.lineTo(250, 250);
/*將連接的直線繪制出來(lái)*/
context.stroke();
}
</script>
<canvas id="canvas" height="300" width="500" style="background-color: #ff0;"></canvas>
</body>
繪制貝塞爾曲線 <small>bezierCurve API參考</small>
-
參數(shù):
- cp1x:第一個(gè)控制點(diǎn)的 x 軸坐標(biāo);
- cp1y:第一個(gè)控制點(diǎn)的 y 軸坐標(biāo)赴穗;
- cp2x:第二個(gè)控制點(diǎn)的 x 軸坐標(biāo)憔四;
- cp2y:第二個(gè)控制點(diǎn)的 y 軸坐標(biāo);
- x:結(jié)束點(diǎn)的 x 軸坐標(biāo)望抽;
- y:結(jié)束點(diǎn)的 y 軸坐標(biāo)加矛。
- 重點(diǎn):繪制beziercurve重點(diǎn)在于掌握cp1和cp2兩個(gè)點(diǎn)的控制;曲線的起點(diǎn)為畫(huà)筆的起點(diǎn)煤篙,曲線的終點(diǎn)為參數(shù)x斟览,y的坐標(biāo),曲線的彎曲度由cp1和cp2兩個(gè)點(diǎn)位置的牽引力決定辑奈。
<body>
<!-- beziercurve demo -->
<script>
window.onload = function() {
var canvas = document.getElementById("canvas");
if (canvas == null) {
return false;
}
var ctx = canvas.getContext("2d");
ctx.strokeStyle = "#ddd";
ctx.lineWidth = 1;
//畫(huà)橫線苛茂,y軸每隔10個(gè)像素畫(huà)一條橫線
for (var i = 0.5; i < 500; i++) {
//創(chuàng)建路徑,如果沒(méi)有此方法鸠窗,循環(huán)會(huì)導(dǎo)致里面的線會(huì)重復(fù)渲染妓羊。可比較"畫(huà)橫線"與"畫(huà)豎線"的區(qū)別稍计。
//ctx.beginPath();
ctx.moveTo(0, i * 10);
ctx.lineTo(500, i * 10);
//若該渲染方法寫在for循環(huán)之外躁绸,即使沒(méi)有beginPath()方法,也不會(huì)重復(fù)渲染臣嚣。
ctx.stroke();
}
//畫(huà)豎線净刮,x軸每隔10個(gè)像素畫(huà)一條豎線
for (var i = 0.5; i < 500; i++) {
ctx.beginPath();
ctx.moveTo(i * 10, 0);
ctx.lineTo(i * 10, 500);
ctx.stroke();
}
// beziercurve begin
ctx.beginPath();
ctx.moveTo(100, 100);
ctx.bezierCurveTo(100, 400, 400, 400, 400, 100);
//如果圖形已經(jīng)是封閉的或者只有一個(gè)點(diǎn),那么此方法不會(huì)做任何操作硅则。否則該方法會(huì)嘗試從當(dāng)前點(diǎn)到起始點(diǎn)繪制一條直線淹父。
// ctx.closePath();
ctx.strokeStyle = "#f00";
ctx.stroke();
// beziercurve end
/*下方代碼更好的說(shuō)明bezierCurverTo六個(gè)參數(shù)的作用*/
//第一個(gè)控制點(diǎn),曲線的牽引方向點(diǎn)怎虫;bezierCurveTo第一個(gè)x暑认,y
drawArc(ctx, 100, 400, 5, 0, 2 * Math.PI, "#f00", "控制點(diǎn)1");
//第二個(gè)控制點(diǎn)困介,曲線的牽引方向點(diǎn);bezierCurveTo第二個(gè)x蘸际,y
drawArc(ctx, 400, 400, 5, 0, 2 * Math.PI, "#f00", "控制點(diǎn)2");
//開(kāi)始點(diǎn)座哩,moveTo的點(diǎn)
drawArc(ctx, 100, 100, 5, 0, 2 * Math.PI, "#00f", "起始點(diǎn)");
//結(jié)束點(diǎn),相當(dāng)于lineTo的點(diǎn)捡鱼;bezierCurveTo第三個(gè)x八回,y
drawArc(ctx, 400, 100, 5, 0, 2 * Math.PI, "#00f", "結(jié)束點(diǎn)");
}
// 繪制一個(gè)圓點(diǎn)及旁注
function drawArc(ctx, x, y, r, startAngle, endAngle, color, txt) {
ctx.beginPath();
ctx.arc(x, y, r, startAngle, endAngle);
ctx.fillStyle = color;
ctx.fill();
ctx.strokeStyle = color;
// 繪制字符
ctx.strokeText(txt, x + r + 5, y);
}
</script>
<canvas id="canvas" width="500" height="500"></canvas>
</body>
效果圖如下:
Canvas的漸變
漸變過(guò)程中的顏色均使用
漸變對(duì)象.addColorStop(offset,color)
方法設(shè)置,多少種顏色漸變就添加多少次此方法驾诈。
- 線性漸變LinearGradient
該漸變對(duì)象只定義漸變的起始與終點(diǎn)位置及漸變的角度缠诅,在該兩點(diǎn)位置之間實(shí)現(xiàn)對(duì)應(yīng)角度的漸變。
漸變的有效范圍:在canvas范圍內(nèi)根據(jù)兩點(diǎn)位置及角度決定了漸變范圍乍迄。<small>關(guān)于漸變色的角度:漸變色位于兩點(diǎn)構(gòu)成直線的垂直線范圍內(nèi)</small>
1. 創(chuàng)建LinearGradient對(duì)象
`var lgradient = ctx.createLinearGradient(xstart,ystart,xend,yend)`
2. 添加漸變顏色`lgradient.addColorStop(offset,color)`<small>多少種顏色漸變就添加多少次此方法</small>
3. 將圖形繪制(`ctx.fillRect等`)在漸變對(duì)象有效的canvas范圍內(nèi)(非漸變對(duì)象的參數(shù)范圍)
<!--LinearGradient & 角度弧度轉(zhuǎn)化 & 根據(jù)角度管引、圓心、半徑獲取旋轉(zhuǎn)后的目標(biāo)坐標(biāo) DEMO-->
<body>
<script>
window.onload = function() {
var canvas = document.getElementById("canvas");
if (canvas == null) {
return false;
}
var ctx = canvas.getContext("2d");
// 創(chuàng)建一個(gè)線性漸變對(duì)象闯两,并指定起始x,y坐標(biāo)及結(jié)束x,y坐標(biāo)
var gradient = ctx.createLinearGradient(0, 0, 100, 50);
// 漸變色添加 begin褥伴;真正的漸變?yōu)間radient范圍內(nèi)的50%到80%之間,從白色漸變到綠色
// offset=0.8漾狼,表示green的正色在gradient范圍的80%處(從左往右)重慢;該offset后的范圍均為green正色
gradient.addColorStop(0.8, "green");
// offset=0.5,表示white的正色在gradient范圍的50%處(從左往右)逊躁;該offset前的范圍均為white正色
gradient.addColorStop(0.5, "white");
// 漸變色添加 end
ctx.fillStyle = gradient;
// 此處300已超出LinearGradient對(duì)象的范圍及角度產(chǎn)生的漸變范圍似踱,故超出有效漸變范圍會(huì)根據(jù)addColorStop設(shè)置的偏移和顏色決定,此處顯示green色稽煤。
ctx.fillRect(10, 10, 300, 100);
// 漸變的范圍核芽,超出該范圍,都使用接近的正色
ctx.strokeStyle = "#E3C41B";
ctx.strokeRect(0, 0, 100, 50);
// 繪制漸變的方向
ctx.beginPath();
ctx.moveTo(0, 0);
ctx.lineTo(100, 50);
ctx.stroke();
// 求斜線的長(zhǎng)度酵熙,得出半徑
var r = Math.sqrt(Math.pow(100, 2) + Math.pow(50, 2)) / 2;
ctx.beginPath();
ctx.moveTo(50, 25);
var degree = getDegree(0, 0, 100, 50);
// 注:*****所有的角度都根據(jù)當(dāng)時(shí)坐標(biāo)點(diǎn)上的坐標(biāo)軸計(jì)算,正數(shù)則按順時(shí)針計(jì)算*****
// 1角度=π/180弧度
//dx 應(yīng)該是順時(shí)針偏移斜線與x坐標(biāo)軸的順時(shí)針夾角+90度角算出的x軸坐標(biāo)
var dx = 50 + Math.cos(degree * (Math.PI / 180) + Math.PI / 2) * r;
var dy = 25 + Math.sin(degree * (Math.PI / 180) + Math.PI / 2) * r;
ctx.lineTo(dx, dy);
ctx.strokeStyle = "#f00";
ctx.stroke();
// 弧度的輔助線
ctx.beginPath();
ctx.moveTo(75, 25);
var cpx1 = cpx2 = 100 - 35;
var cpy1 = cpy2 = dy - 30;
ctx.bezierCurveTo(cpx1, cpy1, cpx2, cpy2, dx + (50 - dx) / 2, (dy - 25) / 2 + 25);
ctx.stroke();
ctx.strokeStyle = "#000";
ctx.strokeText("dx,dy參數(shù)中的弧度", cpx1, cpy1);
// 中心點(diǎn)坐標(biāo)軸
ctx.beginPath();
ctx.moveTo(0, 25);
ctx.lineTo(100, 25);
ctx.strokeText("x軸", 100, 25);
ctx.moveTo(100 * 0.5, 0);
ctx.lineTo(100 * 0.5, 100);
ctx.strokeText("y軸 offset:0.5", 100 * 0.5, 100);
// 0.8offset的垂直線
ctx.moveTo(100 * 0.8, 0);
ctx.lineTo(100 * 0.8, 80);
ctx.strokeText("offset:0.8", 100 * 0.8, 80);
ctx.strokeStyle = "#00a";
ctx.stroke();
// 注釋
ctx.strokeText("黃色斜線位置與方向:", 10, 150);
ctx.strokeText("offset就是顏色正色在該斜線x軸上的偏移量;", 10, 170);
ctx.strokeText("圖中所示offset與黃色斜線相交點(diǎn):0.8與0.5兩個(gè)點(diǎn);", 10, 190);
ctx.strokeText("兩色之間做漸變轧简,根據(jù)斜線方向及整個(gè)屏幕范圍漸變;", 10, 210);
ctx.strokeText("將圖形的style設(shè)置為漸變對(duì)象,并在漸變屏幕范圍", 10, 230);
ctx.strokeText("內(nèi)繪制即可得到漸變效果", 10, 250);
}
//獲取兩點(diǎn)之間的直線與起始點(diǎn)坐標(biāo)x軸順時(shí)針的角度
function getDegree(sx, sy, dx, dy) {
// 直角的邊長(zhǎng)
var x = Math.abs(sx - dx);
var y = Math.abs(sy - dy);
// 根據(jù)勾股定理 斜邊的平方 = 兩直角邊的平方之和
var z = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
// cos
var cos = x / z;
// 獲取弧度
var angle = Math.acos(cos);
// 轉(zhuǎn)化為角度匾二;1弧度 = 180/π角度
var degree = 180 / Math.PI * angle;
console.log(degree);
return degree;
}
</script>
<canvas id="canvas" height="500" width="500"></canvas>
以上代碼效果圖如下所示:
- 徑向漸變RadialGradient
該漸變對(duì)象實(shí)現(xiàn)射線式徑向漸變哮独,其有效范圍為:通過(guò)起始圓形兩邊射線到結(jié)束圓形兩邊并相匯處
1. 創(chuàng)建RadialGradient對(duì)象
`var lgradient = ctx.createRadialGradient(xstart,ystart,rstart,xend,yend,rend)`
2. 添加漸變顏色`lgradient.addColorStop(offset,color)`<small>多少種顏色漸變就添加多少次此方法</small>
3. 將圖形繪制(`ctx.fillRect等`)在漸變對(duì)象有效范圍內(nèi)(非漸變對(duì)象的參數(shù)范圍)
<!-- RadialGradient Demo-->
<body>
<script>
window.onload = function() {
var canvas = document.getElementById("canvas");
if (canvas == null) {
return false;
}
var ctx = canvas.getContext("2d");
// 創(chuàng)建射線(徑向)漸變對(duì)象,六個(gè)參數(shù)分別是:起始圓形坐標(biāo)x察藐,y借嗽,半徑,結(jié)束圓形坐標(biāo)x转培,y,半徑浆竭;
// 通過(guò)起始圓形兩邊射線到結(jié)束圓形兩邊并相匯是結(jié)束
var radiaGradient = ctx.createRadialGradient(50, 50, 50, 200, 200, 400);
// 設(shè)置三個(gè)漸變顏色
radiaGradient.addColorStop(0.3, "#ff0");
radiaGradient.addColorStop(0.8, "rgb(255,140,0");
radiaGradient.addColorStop(1, "rgb(255,0,0");
// 設(shè)置填充顏色為漸變對(duì)象
ctx.fillStyle = radiaGradient;
// 繪制一個(gè)矩形
ctx.fillRect(0, 0, 500, 500);
}
</script>
<canvas id="canvas" height="500" width="500"></canvas>
以上代碼效果圖如下:
Canvas的縮放浸须、平移惨寿、旋轉(zhuǎn)與ctx的狀態(tài)保存及還原
- 縮放:scale(x,y):x,y為縮放因子删窒,會(huì)影響縮放對(duì)象的所有參數(shù)(如寬高裂垦、坐標(biāo)、偏移量肌索,但不影響角度)蕉拢;
- 平移:translate(x,y):x,y為坐標(biāo)軸的偏移量诚亚,即x表示目標(biāo)x軸與當(dāng)前x軸的距離晕换,y表示目標(biāo)y軸與當(dāng)前y軸的距離;
- 旋轉(zhuǎn):rotate(angle):旋轉(zhuǎn)的弧度站宗;angle = degree * (Math.PI / 180) 闸准;degree為角度。旋轉(zhuǎn)后梢灭,ctx的原坐標(biāo)軸也會(huì)隨著旋轉(zhuǎn)夷家,旋轉(zhuǎn)后的ctx狀態(tài)會(huì)導(dǎo)致后期繪制的圖形其坐標(biāo)軸也是基于旋轉(zhuǎn)后的坐標(biāo)軸繪制的;
注意三個(gè)方法前后順序的變化所產(chǎn)生的影響敏释。
1.translate库快、rotate、scale作用的是整個(gè)ctx
2.rotate的旋轉(zhuǎn)的是ctx環(huán)境钥顽,是根據(jù)ctx的當(dāng)前坐標(biāo)軸x軸進(jìn)行的义屏,正弧度表示順時(shí)針,反之逆時(shí)針耳鸯;旋轉(zhuǎn)后起始坐標(biāo)軸更新到旋轉(zhuǎn)后的坐標(biāo)軸狀態(tài)
3.translate的參數(shù)為距x軸的距離湿蛔,距y軸的距離;即起始點(diǎn)x,y的偏移量;同樣是根據(jù)ctx的當(dāng)前狀態(tài)坐標(biāo)軸進(jìn)行
translate、rotate县爬、scale會(huì)被ctx記錄狀態(tài)阳啥,值會(huì)被疊加
- ctx.save():將當(dāng)前上下文狀態(tài)保存,以便后期使用财喳;以便某狀態(tài)被覆蓋的時(shí)候使用察迟;
- ctx.restore():還原至最近save的上下文狀態(tài)。
<!--scale translate rotate & save restore demo-->
<body>
<script>
window.onload = function() {
var canvas = document.getElementById("canvas");
if (canvas == null) {
return false;
}
var ctx = canvas.getContext("2d");
ctx.strokeStyle = "#ddd";
ctx.lineWidth = 1;
//畫(huà)橫線耳高,y軸每隔10個(gè)像素畫(huà)一條橫線
for (var i = 0.5; i < 500; i++) {
//創(chuàng)建路徑扎瓶,如果沒(méi)有此方法,循環(huán)會(huì)導(dǎo)致里面的線會(huì)重復(fù)渲染泌枪「藕桑可比較"畫(huà)橫線"與"畫(huà)豎線"的區(qū)別。
//ctx.beginPath();
ctx.moveTo(0, i * 10);
ctx.lineTo(500, i * 10);
//若該渲染方法寫在for循環(huán)之外碌燕,即使沒(méi)有beginPath()方法误证,也不會(huì)重復(fù)渲染继薛。
ctx.stroke();
}
//畫(huà)豎線,x軸每隔10個(gè)像素畫(huà)一條豎線
for (var i = 0.5; i < 500; i++) {
ctx.beginPath();
ctx.moveTo(i * 10, 0);
ctx.lineTo(i * 10, 500);
ctx.stroke();
}
ctx.fillStyle = "#ff0";
ctx.fillRect(50, 50, 50, 100);
// 保存當(dāng)前狀態(tài)
ctx.save();
ctx.translate(50, 50);
ctx.fillStyle = "#0f0";
ctx.fillRect(50, 50, 50, 100);
// 使用restore后愈捅,最近的save狀態(tài)就會(huì)被彈出遏考;
ctx.restore();
// 重新保存還原后得到的第一個(gè)save狀態(tài)
ctx.save();
for (var i = 0; i < 3; i++) {
// ctx.scale(0.9, 0.9);
// x,y分別正向偏移各50像素
ctx.translate(50, 50);
ctx.fillStyle = "rgba(255,0,0,0.25)";
// 以偏移后的50,50坐標(biāo)點(diǎn)做為起始的0,0坐標(biāo)點(diǎn)蓝谨,下方的50,50坐標(biāo)點(diǎn)以原始0,0計(jì)算則為100,100的坐標(biāo).
ctx.fillRect(50, 50, 100, 20);
}
// 恢復(fù)到save保存的狀態(tài)
ctx.restore();
ctx.translate(300, 300);
// ctx會(huì)記錄繪制的狀態(tài)灌具,循環(huán)會(huì)導(dǎo)致在記錄的狀態(tài)下不斷的scale,不斷的translate譬巫。
for (var i = 0; i < 50; i++) {
// 先縮放咖楣,后平移,會(huì)導(dǎo)致平移的50,50偏移量隨縮放因子改變缕题,及x,y實(shí)際偏移量分別為45,45截歉。
// 即使先平移,后縮放烟零,因循環(huán)也會(huì)導(dǎo)致平移的參數(shù)隨縮放因子發(fā)生變化瘪松。
// 說(shuō)明ctx的狀態(tài)被實(shí)時(shí)覆蓋保存,除非通過(guò)save()存檔副本
ctx.scale(0.9, 0.9);
ctx.translate(10, 10);
// 順時(shí)針30度角旋轉(zhuǎn)
ctx.rotate(30 * Math.PI / 180);
ctx.fillStyle = "rgba(0,0,255,0.25)";
// scale的縮放因子為0.9,所以實(shí)際坐標(biāo)為偏移后的x坐標(biāo)+45,偏移后的y坐標(biāo)+0锨阿;寬高為90,18宵睦。
ctx.fillRect(50, 0, 100, 20);
}
}
</script>
<canvas id="canvas" width="500" height="500"></canvas>
</body>
以上代碼效果圖如下:
/* translate rotate 重要知識(shí)點(diǎn) */
/* 重點(diǎn):
* 1.translate壳嚎、rotate、scale作用的是整個(gè)ctx
* 2.rotate的旋轉(zhuǎn)的是ctx環(huán)境末早,是根據(jù)ctx的當(dāng)前坐標(biāo)軸x軸進(jìn)行的烟馅,正弧度表示順時(shí)針,反之逆時(shí)針然磷;旋轉(zhuǎn)后起始坐標(biāo)軸更新到旋轉(zhuǎn)后的坐標(biāo)軸狀態(tài)
* 3.translate的參數(shù)為距x軸的距離郑趁,距y軸的距離;即起始點(diǎn)x,y的偏移量;同樣是根據(jù)ctx的當(dāng)前狀態(tài)坐標(biāo)軸進(jìn)行
* translate、rotate姿搜、scale會(huì)被ctx記錄狀態(tài)寡润,值會(huì)被疊加
* */
var secCanvas = document.getElementById("secCanvas");
secCanvas.style.backgroundColor = "#ccc";
ctx = secCanvas.getContext("2d");
for(var i = 0; i < 2; i++) {
ctx.beginPath();
//標(biāo)識(shí)ctx的起始點(diǎn) beigin (藍(lán)色原點(diǎn))
ctx.arc(0, 0, 5, 0, 2 * Math.PI, false);
ctx.fill();
//標(biāo)識(shí)ctx的起始點(diǎn) end
ctx.fillStyle = "royalblue";
//scale不影響角度,只影響寬高舅柜、坐標(biāo)梭纹、偏移量
//ctx.scale(0.9,0.9);
var angle = 45 * (Math.PI / 180);
//基于起點(diǎn)坐標(biāo)軸x軸順時(shí)針旋轉(zhuǎn)45度角
//rotate后,ctx的整個(gè)坐標(biāo)軸就旋轉(zhuǎn)了45度角(圖中的紅線為旋轉(zhuǎn)后的x軸)
ctx.rotate(angle);/*因?yàn)閏tx會(huì)更新?tīng)顟B(tài)致份,所以會(huì)作用到第二次循環(huán)*/
ctx.save(); /*保存旋轉(zhuǎn)后的狀態(tài),以便下方劃坐標(biāo)軸用*/
//劃旋轉(zhuǎn)angle弧度后的線條 beigin
ctx.beginPath();
ctx.moveTo(0, 0);
//ctx已經(jīng)旋轉(zhuǎn)变抽,這里獲取旋轉(zhuǎn)角度后對(duì)應(yīng)100半徑的坐標(biāo)點(diǎn),角度只需0即可
var dx = Math.cos(0) * 500;
var dy = Math.sin(0) * 500;
ctx.lineTo(dx, dy);
ctx.strokeStyle = "#FF0000";
ctx.stroke();
ctx.font = "14px Consolas";
ctx.strokeStyle = "#228B22";
ctx.strokeText("第"+(i+1)+"個(gè)循環(huán)旋轉(zhuǎn)45度后的x坐標(biāo)軸", dx, dy)
//劃旋轉(zhuǎn)angle弧度后的線條 end
//標(biāo)識(shí)未translate(50,0)前的rect起始點(diǎn)(紅色點(diǎn))
ctx.strokeText("第"+(i+1)+"個(gè)循環(huán)旋轉(zhuǎn)45度后的100,0坐標(biāo)點(diǎn)", 100, 0)
ctx.beginPath();
ctx.arc(100, 0, 5, 0, 2 * Math.PI, false);
ctx.fillStyle = "#FF0000";
ctx.fill();
//基于起點(diǎn)坐標(biāo)軸x,y軸的偏移距離
ctx.translate(50, 0);
ctx.fillRect(100, 0, 100, 50);
//標(biāo)識(shí)translate(50,0)后的rect起始點(diǎn)(黃色點(diǎn))
ctx.strokeText("第"+(i+1)+"個(gè)循環(huán)旋轉(zhuǎn)45度且偏移50,0后的100,0坐標(biāo)點(diǎn)", 100, 20)
ctx.beginPath();
ctx.arc(100, 0, 5, 0, 2 * Math.PI, false);
ctx.fillStyle = "#ff0";
ctx.fill();
//旋轉(zhuǎn)45度后的坐標(biāo)軸
ctx.restore(); /*還原到未translate前*/
ctx.beginPath();
//劃第一個(gè)100,0坐標(biāo)點(diǎn)的y軸
//移動(dòng)到第一個(gè)100,0坐標(biāo)點(diǎn)(紅色)
ctx.moveTo(100, -100);
ctx.lineTo(100, 100);
ctx.stroke();
ctx.font = "14px Arial";
ctx.strokeText("第"+(i+1)+"個(gè)循環(huán)旋轉(zhuǎn)45度后的y坐標(biāo)軸", 110, -100);
//劃第二個(gè)100,0坐標(biāo)點(diǎn)的y軸
ctx.beginPath();
//基于第一個(gè)100,0坐標(biāo)點(diǎn)绍载,x軸方向偏移50
ctx.translate(50, 0)/*將作用于第二次循環(huán)的ctx起始點(diǎn)*/
//實(shí)際moveTo(150,-100)
ctx.moveTo(100, -100);
ctx.lineTo(100, 100);
ctx.stroke();
}