文章目錄
- JavaScript繪圖
- 使用canvas
- 繪制圖形
-
- 定義樣式和顏色
-
- 圖形變形
- 保存和恢復狀態
- 清除畫布
- 移動坐標
- 旋轉坐標
- 縮放圖形
- 變換圖形
- 圖形合成
-
- 繪制文本
-
- 文本樣式
-
JavaScript繪圖
HTML5新增了Canvas API,允許js在<canvas>標簽識別的畫布上繪制圖形,創建動畫,設置設計實時視頻處理或渲染。借助一套編程接口,用戶可以在頁面上繪制出任何漂亮的圖形。
【學習重點】
- 使用canvas元素。
- 繪制圖形。
- 設置圖形樣式。
- 靈活使用Canvas API設計網頁動畫。
使用canvas
在HTML5文檔中,使用<canvas>標簽可以在網頁中創建一塊畫布。用法如下:
<canvas id="muCanvas" width="200" height="100"></canvas>
該標簽包括三個屬性:
- id:用來標識畫布,以方便js腳本對其引用。
- width:設置canvas的寬度。
- height:設置canvas的高度。
注意:與<img>不同,<canvas>需要結束標簽</canvas>。如果結束標簽不存在,則文檔的其余部分會被認為是替代內容,將不會顯示出來。
<canvas id="muCanvas" style="border:1px solid;" width="200" height="100"></canvas>
使用js可以在canvas畫布內繪畫,或者設置動畫。
【操作步驟】
- 第一步,在HTML頁面中添加<canvas>標簽,設置canvas的id屬性值以便js調用。
<canvas id
="myCanvas" width
="200" height
="100">
- 第二步,在js腳本中使用document.getELementById()方法,根據canvas元素的id獲取對canvas的應用。
var c
= document
.getElementById("myCanvas");
- 第三步,通過canvas元素的getContext()方法獲取畫布上下文(context),創建context對象,以獲取允許進行繪制的2D環境。
var context
= c
.getContext("2d");
getContext(“2d”)方法返回一個畫布渲染上下文對象,使用該對象可以在canvas元素中繪制圖形,參數2d表示二維繪圖。
context
.fillStyle
= "pink";
context
.fillRect(50, 25, 100, 50);
這兩行代碼中,fillStyle屬性定義將要繪制的矩形的填充顏色為粉色,fillRect()方法制定了要繪制的矩形的位置和尺寸。圖形的位置由前面的canvas坐標值決定,尺寸由后面的寬度和高度值決定。完整代碼:
<script>window.onload = function() {var c = document.getElementById("myCanvas");var context = c.getContext("2d");context.fillStyle = "pink";context.fillRect(50, 25, 100, 50);}
</script><body><canvas id="myCanvas" style="border: 1px solid;" width="200" height="100"></canvas>
</body>
fillRect(50, 25, 100, 50)方法可以用來繪制矩形圖形,它的前兩個參數用于繪制圖形的x軸和y軸坐標,后面兩個參數設置繪制矩形的寬度和高度。
繪制圖形
本節將介紹一些基本圖形的繪制,包括矩形、直線、圓形、曲線等形狀或路徑。
矩形
canvas提供了3種方法繪制矩形。
- fillRect(x, y, width, height):繪制一個填充的矩形。
- strokeRect(x, y, width, height):繪制一個矩形的邊框。
- clearRect(x, y, width, height):清除指定矩形區域,讓清除部分完全透明。
參數說明:
- x:矩形左上角的x坐標。
- y:矩形左上角的y坐標。
- width:矩形的寬度,以像素為單位。
- height:矩形的高度,以像素為單位。
- 【實例】下面實例分別使用上面三種方法。
<script>window.onload = function() {draw();function draw() {var canvas = document.getElementById("canvas");if (canvas.getContext) {var ctx = canvas.getContext('2d');ctx.fillRect(25, 25, 100, 100);ctx.clearRect(45, 45, 60, 60);ctx.strokeRect(50, 50, 50, 50);}}}
</script><body><canvas id="canvas" style="border: 1px solid #999;" width="300" height="200"></canvas>
</body>
路徑
使用路徑繪制圖形的步驟如下:
第一步,創建路徑起始點。
第二布,使用畫圖命令繪制路徑。
第三步,封閉路徑。
第四步,生成路徑之后,可以通過描邊或填充路徑區域來渲染圖形。
需要調用的方法說明如下:
- beginPath():開始路徑。
- closePath():閉合路徑。閉合路徑之后圖形繪制命令又重新指向上下文。
- stroke():描邊路徑。通過線條來繪制圖形輪廓。
- fill():填充路徑。通過填充路徑的內容區域生成實心的圖形。
- 提示:生成路徑的第一步是調用beginPath()方法。每次調用這個方法之后,表示開始重新繪制新的圖形。閉合路徑closePath()方法不是必需的;當調用fill()方法時,所有沒有閉合的形狀都會自動閉合,所以不需要調用closePath()方法;但是調用stroke()方法時不會自動閉合。
- 【實例】下面實例演示繪制一個笑臉。
<script
>window
.onload = function() {draw();function draw() {var canvas
= document
.getElementById("canvas");if (canvas
.getContext
) {var ctx
= canvas
.getContext('2d');ctx
.beginPath();ctx
.arc(75, 75, 50, 0, Math
.PI * 2, true);ctx
.moveTo(110, 75);ctx
.arc(75, 75, 35, 0, Math
.PI, false);ctx
.moveTo(65, 65);ctx
.arc(60, 65, 5, 0, Math
.PI * 2, true);ctx
.moveTo(95, 65);ctx
.arc(90, 65, 5, 0, Math
.PI * 2, true);ctx
.stroke();}}}
</script
><body
><canvas id
="canvas" style
="border: 1px solid #999;" width
="300" height
="200"></canvas
>
</body
>
上面代碼中使用arc()方法,調用它可以繪制圓形,接下來詳細講解。
圓弧
使用arc()方法可以繪制弧或者圓。用法如下:
context
.arc(x
,y
,r
,sAngle
,eAngle
,counterclockwise
);
參數說明:
- x:圓心的x坐標。
- y:圓心的y坐標。
- r:圓的半徑。
- sAngle:起始角,以弧度計。提示,弧的圓形的三點鐘位置是0度。
- eAngle:結束角,以弧度計。
- counterclockwise:可選參數,定義繪圖方法。false為順時針,為默認值;true為逆時針。
如果使用arc()創建圓,可以把起始點設置為0,結束角設置為2*Math.PI。
- 【實例】下面實例繪制了12個不同的角度以及填充的圓弧。主要使用兩個for循環,生成圓弧的行列坐標。每一段圓弧的開始都調用beginPath()方法。代碼中,每個圓弧的參數都是可變的,(x,y)坐標是可變的,半徑(radius)和開始角(startAngle)都是固定的。結束角度(endAngle)在第一列開始時是180度(半圓),然后每列增加90度。最后一列形成一個完整的圓。
<script>window.onload = function() {draw();function draw() {var canvas = document.getElementById("canvas");if (canvas.getContext) {var ctx = canvas.getContext("2d");for (var i = 0; i < 4; i++) {for (var j = 0; j < 3; j++) {ctx.beginPath();var x = 25 + j * 50;var y = 25 + i * 50;var radius = 20;var startAngle = 0;var endAngle = Math.PI + (Math.PI * j) / 2;var anticlockwise = i % 2 == 0 ? false : true;ctx.arc(x, y, radius, startAngle, endAngle, anticlockwise);if (i > 1) {ctx.fill();} else {ctx.stroke();}}}}}}
</script><body><canvas id="canvas" style="border: 1px solid #999;" width="300" height="200"></canvas>
</body>
直線與曲線
使用lineTo()方法可以繪制直線。用法如下:
lineTo(x
,y
)
參數x和y分別表示終點位置的x坐標和y坐標。lineTo(x, y)將繪制一條從當前位置到指定(x, y)位置的直線。
- 【實例1】下面實例繪制兩個三角形,一個是填充的,另一個是描邊的。
<script>window.onload = function() {draw();function draw() {var canvas = document.getElementById("canvas");if (canvas.getContext) {var ctx = canvas.getContext('2d');ctx.beginPath();ctx.moveTo(25, 25);ctx.lineTo(105, 25);ctx.lineTo(25, 105);ctx.fill();ctx.beginPath();ctx.moveTo(125, 125);ctx.lineTo(125, 45);ctx.lineTo(45, 125);ctx.closePath();ctx.stroke();}}}
</script><body><canvas id="canvas" style="border: 1px solid #999;" width="300" height="200"></canvas>
</body>
在上面實例代碼中,從調用beginPath()方法準備繪制一個新的形狀路徑開始,使用movePath()方法移動到目標位置,兩條線段繪制后構成三角形的兩條邊。當路徑使用填充(fill)時路徑會自動閉合。而使用描邊(stroke)命令時則不會自動閉合路徑。如果沒有添加閉合路徑closePath()到描邊三角形中,則只繪制兩條線段,并不是一個完整的三角形。
- 使用arcTo()方法可以繪制曲線,該方法時lineTo()的曲線版,它能夠創建兩條切線之間的弧或曲線。用法如下:
context
.arcTo(x1
, y1
, x2
, y2
, r
);
參數說明:
- x1:弧的起點x坐標。
- y1:弧的起點y坐標。
- x2:弧的終點x坐標。
- y2:弧的終點y坐標。
- r:弧的半徑。
- 【實例2】本實例用lineTo()和arcTo()方法繪制直線和曲線,再連成圓角弧線。
<script>window.onload = function() {draw();function draw() {var canvas = document.getElementById("canvas");if (canvas.getContext) {var ctx = canvas.getContext('2d');ctx.beginPath();ctx.moveTo(20, 20);ctx.lineTo(100, 20);ctx.arcTo(150, 20, 150, 70, 50);ctx.lineTo(150, 120);ctx.stroke();}}}
</script><body><canvas id="canvas" style="border: 1px solid #999;" width="300" height="200"></canvas>
</body>
定義樣式和顏色
canvas支持顏色和樣式選項,如線性、漸變、圖案、透明度和陰影。
顏色
使用fillStyle和strokeStyle屬性可以給圖形上色。其中,fillStyle設置圖形的填充顏色,strokeStyle設置圖形輪廓的顏色。
顏色值可以是表示CSS顏色值的字符串,那么這個新值機會成為新繪制的圖形的默認值。如果要給每個圖形定義不同的顏色,就需要重新設置fillStyle或strokeStyle的值。
- 【實例1】本實例嵌套for循環繪制方陣列表,每個方格填充不同顏色。
<script
>window
.onload = function() {draw();function draw() {var canvas
= document
.getElementById("canvas");if (canvas
.getContext
) {var ctx
= canvas
.getContext('2d');for (var i
= 0; i
< 6; i
++) {for (var j
= 0; j
< 6; j
++) {ctx
.fillStyle
= 'rgb(' + Math
.floor(255 - 42.5 * i
) + ',' + Math
.floor(255 - 42.5 * j
) + ', 0)';ctx
.fillRect(j
* 25, i
* 25, 25, 25);}}}}}
</script
><body
><canvas id
="canvas" style
="border: 1px solid #999;" width
="300" height
="200"></canvas
>
</body
>
在嵌套for結構中,使用變量i和j為每一個方格產生唯一的RGB色彩值,其中僅修改紅綠色通道的值,保持藍色通道的值不變。
不透明度
使用globalAlpha全局屬性可以設置繪制圖形的不透明度,另外也可以通過色彩的不透明度參數來為圖形設置不透明度。相對與使用globalAlpha屬性來說,這種方法更靈活些。使用rgba(R, G, B, A)方法可以設置具有不透明度的顏色。
rgba(R, G, B, A)
其中R、G、B將顏色的紅色、綠色和藍色分別指定為0~255之間的十進制整數;A把alpha(不透明)成分指定為0.0-1.0之間的一個浮點數值,0.0為完全透明,1.0表示完全不透明。
- 【實例】下面實例使用四色格作為背景,設置globalAlpha為0.2后,在上面畫一系列半徑遞增的半透明圓,最終結果是一個經向漸變效果。圓疊加的越多,原來所畫的圓的透明度就越低。通過增加循環次數,畫更多的圓,背景圖中心部分會完全消失。
<script>window.onload = function() {draw();function draw() {var canvas = document.getElementById("canvas");if (canvas.getContext) {var ctx = canvas.getContext('2d');ctx.fillStyle = '#FD0';ctx.fillRect(0, 0, 75, 75);ctx.fillStyle = '#6C0';ctx.fillRect(75, 0, 75, 75);ctx.fillStyle = '#09F';ctx.fillRect(0, 75, 75, 75);ctx.fillStyle = '#F30';ctx.fillRect(75, 75, 75, 75);ctx.globalAlpha = 0.2;for (var i = 0; i < 7; i++) {ctx.beginPath();ctx.arc(75, 75, 10 + 10 * i, 0, Math.PI * 2, true);ctx.fill();}}}}
</script><body><canvas id="canvas" style="border: 1px solid #999;" width="300" height="200"></canvas>
</body>
實線
線的粗細
使用lineWidth屬性可以設置線條的粗細,取值必須為正值,默認為1.0。
- 【實例1】下面實例使用for循環繪制了12條線寬一次遞增的線段。
<script>window.onload = function() {draw();function draw() {var canvas = document.getElementById("canvas");if (canvas.getContext) {var ctx = canvas.getContext('2d');for (var i = 0; i < 12; i++) {ctx.strokeStyle = "red";ctx.lineWidth = 1 + i;ctx.beginPath();ctx.moveTo(5, 5 + i * 14);ctx.lineTo(140, 5 + i * 14);ctx.stroke();}}}}
</script><body><canvas id="canvas" style="border: 1px solid #999;" width="300" height="200"></canvas>
</body>
端點樣式
lineCap屬性用于設置線段端點的樣式,包括三種:butt、round和square,默認為butt。
- 【實例2】下面實例繪制了三條藍色的直線段,并依次設置上述三種屬性值,兩側有兩條紅色的參考線,以方便觀察。
<script>window.onload = function() {draw();function draw() {var canvas = document.getElementById("canvas");if (canvas.getContext) {var ctx = canvas.getContext('2d');var lineCap = ['butt', 'round', 'square'];ctx.strokeStyle = 'red';ctx.beginPath();ctx.moveTo(10, 10);ctx.lineTo(10, 150);ctx.moveTo(150, 10);ctx.lineTo(150, 150);ctx.stroke();ctx.strokeStyle = 'blue';for (var i = 0; i < lineCap.length; i++) {ctx.lineWidth = 20;ctx.lineCap = lineCap[i];ctx.beginPath();ctx.moveTo(10, 30 + i * 50);ctx.lineTo(150, 30 + i * 50);ctx.stroke();}}}}
</script><body><canvas id="canvas" style="border: 1px solid #999;" width="300" height="200"></canvas>
</body>
連接樣式
lineJoin屬性用于設置兩條線段連接處的樣式。包括三種樣式:round、bevel和miter,默認值為miter。
- 【實例3】下面實例繪制了三條藍色的直線,并以此設置三個屬性值,觀察拐角處(即直角段連接處)樣式的區別。
<script>window.onload = function() {draw();function draw() {var canvas = document.getElementById("canvas");if (canvas.getContext) {var ctx = canvas.getContext('2d');var lineJoin = ['round', 'bevel', 'miter'];ctx.strokeStyle = 'blur';for (var i = 0; i < lineJoin.length; i++) {ctx.lineWidth = 25;ctx.lineJoin = lineJoin[i];ctx.beginPath();ctx.moveTo(10 + i * 150, 30);ctx.lineTo(100 + i * 150, 30);ctx.lineTo(100 + i * 150, 100);ctx.stroke();}}}}
</script><body><canvas id="canvas" style="border: 1px solid #999;" width="300" height="200"></canvas>
</body>
交點方式
miterLimit屬性用于設置兩條線段連接處交點的繪制方式,其作用是為斜面的長度設置一個上限,默認為10,即規定斜面的長度不能超過線條寬度的10倍。當斜面的長度達到線條寬度的10倍時,就會變為斜角。如果lineJoin屬性round或bevel時,miterLimit屬性無效。
- 【實例4】通過下面實例可以觀察到,當角度和miterLimit屬性值發生變化時斜面長度的變化。在運行代碼之前,也可以將miterLimit屬性值改為固定值,以觀察不同的值產生的結果。
<script
>window
.onload = function() {draw();function draw() {var canvas
= document
.getElementById("canvas");if (canvas
.getContext
) {var ctx
= canvas
.getContext('2d');for (var i
= 1; i
< 10; i
++) {ctx
.strokeStyle
= 'blue';ctx
.lineWidth
= 10;ctx
.lineJoin
= 'miter';ctx
.miterLimit
= i
* 10;ctx
.beginPath();ctx
.moveTo(10, i
* 30);ctx
.lineTo(100, i
* 30);ctx
.lineTo(10, 33 * i
);ctx
.stroke();}}}}
</script
><body
><canvas id
="canvas" style
="border: 1px solid #999;" width
="300" height
="200"></canvas
>
</body
>
虛線
使用setLineDash()方法和lineDashOffset屬性可以定義虛線樣式。setLineDash()方法接受一個數組來指定線段與間隙的交替,lineDashOffset屬性設置起始偏移量。
- 【實例】下面實例繪制一個矩形虛線框,然后使用定時器設計每隔0.5秒重新繪制一次,重繪時改變lineDashOffset屬性值,從而創建一個行軍蟻的效果。
<script>window.onload = function() {var ctx = document.getElementById("canvas").getContext('2d');var offset = 0;function draw() {ctx.clearRect(0, 0, canvas.width, canvas.height);ctx.setLineDash([4, 4]);ctx.lineDashOffset = -offset;ctx.strokeRect(50, 50, 200, 100);}function march() {offset++;if (offset > 16) {offset = 0;}draw();setTimeout(march, 100);}march();}
</script><body><canvas id="canvas" style="border: 1px solid #999;" width="300" height="200"></canvas>
</body>
要繪制線性漸變,首先使用createLinearGradient()方法創建canvasGradient對象,然后使用addColorStop()方法進行上色。
createLinearGradient()方法用法如下:
context
.createLinearGradient(x0
, y0
, x1
, y1
);
參數說明:
- x0:漸變開始點的x坐標。
- y0:漸變開始點的y坐標。
- x1:漸變結束點的x坐標。
- y1:漸變結束點的y坐標。
addColorStop()方法用法如下:
gradient
.addColorStop(stop
, color
);
參數說明:
- stop:介于0.0-1.0之間的值,表示漸變開始與結束之間的相對位置。漸變起點的偏移值為0,重點的偏移值為1.如果position值為0.5,則表示色標出現在漸變的正中間。
- color:在結束位置顯示的css顏色值。
- 【實例】下面實例演示如何繪制線性漸變。
<script>window.onload = function() {draw();function draw() {var ctx = document.getElementById("canvas").getContext('2d');var lingrad = ctx.createLinearGradient(0, 0, 0, 200);lingrad.addColorStop(0, '#ff0000');lingrad.addColorStop(1 / 7, '#ff9900');lingrad.addColorStop(2 / 7, '#ffff00');lingrad.addColorStop(3 / 7, '#00ff00');lingrad.addColorStop(4 / 7, '#00ffff');lingrad.addColorStop(5 / 7, '#0000ff');lingrad.addColorStop(6 / 7, '#ff00ff');lingrad.addColorStop(1, '#ff0000');ctx.fillStyle = lingrad;ctx.strokeStyle = lingrad;ctx.fillRect(0, 0, 300, 200);}}
</script><body><canvas id="canvas" style="border: 1px solid #999;" width="300" height="200"></canvas>
</body>
使用addColorStop()可以添加多個色標,色標可以在0-1之間任意位置添加。
經向漸變
要繪制經向漸變,首先需要使用createRadialGradient()方法創建canvasGradient對象,然后使用addColorStop()方法進行上色。createRadialGradient()方法的用法:
context
.createRadialGradinet(x0
, y0
, r0
, x1
, y1
, r1
);
參數說明:
- x0:漸變開始圓的x坐標。
- y0:漸變開始圓的y坐標。
- r0:開始圓的半徑。
- x1:漸變結束圓的x坐標。
- y1:漸變結束圓的y坐標。
- r1:結束圓的半徑。
- 【實例】下面實例使用徑向漸變在畫布中央繪制一個圓球形狀。
<script>window.onload = function() {draw();function draw() {var ctx = document.getElementById("canvas").getContext('2d');var radgrad = ctx.createRadialGradient(150, 100, 0, 150, 100, 100);radgrad.addColorStop(0, '#A7D30C');radgrad.addColorStop(0.9, '#019F62');radgrad.addColorStop(1, 'rgba(1, 159, 98, 0)');ctx.fillStyle = radgrad;ctx.fillRect = (0, 0, 300, 200);}}
</script><body><canvas id="canvas" style="border: 1px solid #999;" width="300" height="200"></canvas>
</body>
圖案
使用createPattern()方法可以繪制圖案效果。用法如下:
context.createPattern(image, "repeat|repeat-x|repeat-y|no-repeat");
參數說明如下:
- image:規定要使用的圖片、畫布或視頻元素。
- repeat:默認值。該模式在水平和垂直方向重復。
- repeat-x:該模式只在水平方向重復。
- repeat-y:該模式只在垂直方向重復。
- no-repeat:該模式只顯示一次(不重復)。
創建圖案步驟與創建漸變有些類似,需要先創建一個pattern對象,然后將其賦予fillStyle屬性或strokeStyle屬性。
<script>window.onload = function() {draw();function draw() {var ctx = document.getElementById("canvas").getContext('2d');var img = new Image();img.src = '../img/doge.jpg';img.onload = function() {var ptrn = ctx.createPattern(img, 'repeat');ctx.fillStyle = ptrn;ctx.fillRect(0, 0, 600, 600);}}}
</script><body><canvas id="canvas" style="border: 1px solid #999;" width="600" height="400"></canvas>
</body>
陰影
創建陰影需要四個屬性:
<script>window.onload = function() {draw();function draw() {var ctx = document.getElementById("canvas").getContext('2d');ctx.shadowOffsetX = 4;ctx.shadowOffsetY = 4;ctx.shadowBlur = 4;ctx.shadowColor = "rgba(0, 0, 0, 0.5)";ctx.font = "60px Times New Roman";ctx.fillStyle = "pink";ctx.fillText("你好佩琪", 5, 80);}}
</script><body><canvas id="canvas" style="border: 1px solid #999;" width="300" height="200"></canvas>
</body>
填充規則
前面介紹了fill()方法可以填充圖形,該方法可以接受兩個值,用來定義填充規則。
- nonzero:非零環繞數規則,為默認值。
- evenodd:奇偶規則。
填充規則根據某處在路徑的外面或者里面來決定是否被填充,這對于路徑相交或者路徑被嵌套的時候極為有用。
<script>window.onload = function() {draw();function draw() {var ctx = document.getElementById("canvas").getContext('2d');ctx.beginPath();ctx.arc(50, 50, 30, 0, Math.PI * 2, true);ctx.arc(50, 50, 15, 0, Math.PI * 2, true);ctx.fill("evenodd");}}
</script><body><canvas id="canvas" style="border: 1px solid #999;" width="300" height="200"></canvas>
</body>
不設置與設置evenodd效果:
圖形變形
本節介紹如何對畫布進行操作,進行變形以便設計復雜圖形。
保存和恢復狀態
canvas狀態存儲在棧中,一個繪畫狀態包括兩部分。
- 當前應用的變形,如移動、旋轉、縮放。包括的樣式屬性:strokeStyle、fillStyle、globalAlpha、lineWidth、lineCap、lineJoin、miterLimit、shadowOffsetX、shadowOffsetY、shadowBlur、shadowColor、globalCompositeOperation。
- 當前裁切路徑。
使用save()方法,可以將當前狀態推送到棧中保存,使用restore()方法可以將上一個保存的狀態從棧中彈出,恢復上一次所有的設置。
- 【實例】下面實例先繪制一個矩形,填充顏色為#ff00ff,輪廓顏色為藍色,然后保存這個狀態,再繪制另外一個矩形,填充顏色為#ff0000,輪廓顏色為綠色;最后恢復第一個矩形的狀態,并繪制兩個小的矩形,其中一個矩形填充顏色必為#ff00ff,另一個矩形輪廓顏色必為藍色。因為此時已經恢復了原來保存的狀態,所以會沿用最先設定的屬性值。
<script>window.onload = function() {draw();function draw() {var ctx = document.getElementById("canvas").getContext('2d');ctx.fillStyle = "#ff00ff";ctx.strokeStyle = "blue";ctx.fillRect(20, 20, 100, 100);ctx.strokeRect(20, 20, 100, 100);ctx.fill();ctx.stroke();ctx.save(); ctx.fillStyle = "#ff0000";ctx.strokeStyle = "green";ctx.fillRect(140, 20, 100, 100);ctx.strokeRect(140, 20, 100, 100);ctx.fill();ctx.stroke();ctx.restore(); ctx.fillRect(20, 140, 50, 50);ctx.strokeRect(80, 140, 50, 50);}}
</script><body><canvas id="canvas" style="border: 1px solid #999;" width="300" height="200"></canvas>
</body>
清除畫布
使用clearRect()方法可以清除指定區域內的所有圖形,顯示畫布背景。
context
.clearRect(x
, y
, width
, height
);
參數說明如下。
<script>window.onload = function() {draw();function draw() {var ctx = document.getElementById("canvas").getContext('2d');ctx.strokeStyle = '#FF00FF';ctx.beginPath();ctx.arc(200, 150, 100, -Math.PI * 1 / 6, -Math.PI * 5 / 6, true);ctx.stroke();var btn = document.getElementsByTagName('input')[0];btn.onclick = function() {ctx.clearRect(0, 0, 300, 200);}}}
</script><body><canvas id="canvas" style="border: 1px solid #999;" width="300" height="200"></canvas><input type="button" name="" value="清空畫布">
</body>
移動坐標
在默認狀態下,畫布以左上角(0, 0)為原點作為繪圖參考。使用translate()方法可以移動坐標原點,這樣新繪制的圖形就以新的坐標原點作為參考進行繪制。其用法如下:
context.translate(dx, dy);
參數dx和dy分別為坐標原點沿水平和垂直兩個方向的偏移量。
<script>window.onload = function() {draw();function draw() {var ctx = document.getElementById("canvas").getContext('2d');ctx.translate(0, 80);for (var i = 1; i < 10; i++) {ctx.save();ctx.translate(60 * i, 0);drawTop(ctx, "rgb(" + (30 * i) + "," + (255 - 30 * i) + ",255)");drawGrip(ctx);ctx.restore();}function drawTop(ctx, fillStyle) {ctx.fillStyle = fillStyle;ctx.beginPath();ctx.arc(0, 0, 30, 0, Math.PI, true);ctx.closePath();ctx.fill();}function drawGrip(ctx) {ctx.save();ctx.fillStyle = "blue";ctx.fillRect(-1.5, 0, 1.5, 40);ctx.beginPath();ctx.strokeStyle = "blue";ctx.arc(-5, 40, 4, Math.PI, Math.PI * 2, true);ctx.stroke();ctx.closePath();ctx.restore();}}}
</script><body><canvas id="canvas" style="border: 1px solid #999;" width="600" height="200"></canvas>
</body>
在瀏覽器中瀏覽效果如圖,可見,canvas中圖形移動的實現,其實是通過改變畫布的坐標原點來實現的,所謂的”移動圖形“,只是看上去的樣子 ,實際移動的是坐標空間。
旋轉坐標
使用rotate()方法可以以原點為中心旋轉canvas上下文對象的坐標空間。用法如下:
context
.rotate(angle
);
rotate()方法只有一個參數,即旋轉角度angle,旋轉角度以順時針方向為正方向,以弧度為單位,旋轉中心為canvas的原點。
- 【實例】在上個實例的基礎上,下面實例設計在每次開始繪制圖形之前,現將做表空間旋轉PI*(2/4+i/4),再將坐標空間沿y軸負方向移動100,然后開始繪制圖形,從而實現圖形沿以中心點平均旋轉分布。
<script>window.onload = function() {draw();function draw() {var ctx = document.getElementById("canvas").getContext('2d');ctx.translate(150, 150);for (var i = 1; i < 9; i++) {ctx.save();ctx.rotate(Math.PI * (2 / 4 + i / 4));ctx.translate(0, -100);drawTop(ctx, "rgb(" + (30 * i) + "," + (255 - 30 * i) + ",255)");drawGrip(ctx);ctx.restore();}function drawTop(ctx, fillStyle) {ctx.fillStyle = fillStyle;ctx.beginPath();ctx.arc(0, 0, 30, 0, Math.PI, true);ctx.closePath();ctx.fill();}function drawGrip(ctx) {ctx.save();ctx.fillStyle = "blue";ctx.fillRect(-1.5, 0, 1.5, 40);ctx.beginPath();ctx.strokeStyle = "blue";ctx.arc(-5, 40, 4, Math.PI, Math.PI * 2, true);ctx.stroke();ctx.closePath();ctx.restore();}}}
</script><body><canvas id="canvas" style="border: 1px solid #999;" width="300" height="300"></canvas>
</body>
縮放圖形
使用scale()方法可以增減canvas上下文對象的像素數目,從而使吸納圖形的放大和縮小。
用法如下:
context.scale(x, y);
其中,x為橫軸的縮放因子,y為縱軸的縮放因子,值必須是正值。如果需要放大圖形,則將參數設置為大于1的數值,如果需要縮小圖形,則將參數設置為小于1的數值,當參數值等于1時則沒有任何效果。
- 【實例】下面實例使用scale(0.95,0.95)來縮小圖形到上次的0.95,共循環80次,同時移動和旋轉坐標空間,從而實現圖形呈螺旋狀由大到小的變化。
<script>window.onload = function() {draw();function draw() {var ctx = document.getElementById("canvas").getContext('2d');ctx.translate(200, 20);for (var i = 1; i < 80; i++) {ctx.save();ctx.translate(30, 30);ctx.scale(0.95, 0.95);ctx.rotate(Math.PI / 12);ctx.beginPath();ctx.fillStyle = "red";ctx.globalAlpha = "0.4";ctx.arc(0, 0, 50, 0, Math.PI * 2, true);ctx.closePath();ctx.fill();}}}
</script><body><canvas id="canvas" style="border: 1px solid #999;" width="300" height="300"></canvas>
</body>
變換圖形
transform()方法可以同時縮放、旋轉、移動和傾斜當前的上下文環境。
context
.transform(a
, b
, c
, d
, e
, f
);
參數說明:
- a:水平縮放繪圖。
- b:水平傾斜繪圖。
- c:垂直傾斜繪圖。
- d:垂直縮放繪圖。
- e:水平移動繪圖。
- f:垂直移動繪圖。
提示:
- translate(x, y)可以用下面方法來代替。
context
.transform(0, 1, 1, 0, dx
, dy
);
或:
context
.transform(1, 0, 0, 1, dx
, dy
);
其中dx為原點沿x軸移動的數值,dy為原點沿y軸移動的數值。
context.transform(m11, 0, 0, m22, 0, 0);
或:
context.transform(0, m12, m21, 0, 0, 0);
其中,dx、dy都為0表示坐標原點不變,m11、m22或m12、m21為沿x、y軸放大的倍數。
- rotate(angle)可以使用下面方法來代替。
context.transform(cos0, sin0, -sin0, cos0, 0, 0);
其中,θ為旋轉角度的弧度值,dx、dy都為0,表示坐標原點不變。
setTransform()方法用于將當前的變化矩陣重置為最初的矩陣,然后以相同的的參數調用transform()方法。用法如下:
context
.setTransform(m11
, m12
, m21
, m22
, dx
, dy
);
- 【實例】下面實例使用setTransform()方法首先將前面已經發生變換的矩陣重置為最初的矩陣,即恢復最初的原點,然后再將坐標原點改為(10,10),并以新坐標為基準繪制藍色矩陣。
<script>window.onload = function() {draw();function draw() {var ctx = document.getElementById("canvas").getContext('2d');ctx.translate(200, 20);for (var i = 1; i < 90; i++) {ctx.save();ctx.transform(0.95, 0, 0, 0.95, 30, 30);ctx.rotate(Math.PI / 12);ctx.beginPath();ctx.fillStyle = "red";ctx.globalAlpha = "0.4";ctx.arc(0, 0, 50, 0, Math.PI * 2, true);ctx.closePath();ctx.fill();}ctx.setTransform(1, 0, 0, 1, 10, 10);ctx.fillStyle = "blue";ctx.fillRect(0, 0, 50, 50);ctx.fill();}}
</script><body><canvas id="canvas" style="border: 1px solid #999;" width="300" height="300"></canvas>
</body>
在本例中,使用scale(0.95, 0.95)來縮小圖形到上次的0.95,共循環89次,同時移動和旋轉做表空間,從而使吸納圖形成螺旋狀由大到小的變化。
圖形合成
合成
當兩個或兩個以上的圖形存在重疊區域時,默認一個圖形畫在前一個圖形之上。通過制定圖形globalCompositeOperation屬性的值可以改變圖形的繪制順序或繪制方式,從而實現更多的可能。
裁切
使用clip()方法能夠從原始畫布中剪切任意形狀和尺寸。其原理與繪制普通canvas圖形類似,只不過clip()的作用是形成一個蒙版,沒有被蒙版的區域會被隱藏。
- 提示:在使用clip()方法前,通過使用save()方法對當前畫布區域進行保存,并可以在以后的任意時間通過restore()方法對其進行恢復。
- 【實例】如果繪制一個圓形,并進行裁切,則圓形之外的區域將不會繪制在canvas上。
<script>window.onload = function() {draw();function draw() {var ctx = document.getElementById("canvas").getContext('2d');ctx.fillStyle = "black";ctx.fillRect(0, 0, 300, 300);ctx.fill();ctx.beginPath();ctx.arc(150, 150, 100, 0, Math.PI * 2, true);ctx.clip();ctx.translate(200, 20);for (var i = 1; i < 90; i++) {ctx.save();ctx.transform(0.95, 0, 0, 0.95, 30, 30);ctx.rotate(Math.PI / 12);ctx.beginPath();ctx.fillStyle = "red";ctx.globalAlpha = "0.4";ctx.arc(0, 0, 50, 0, Math.PI * 2, true);ctx.closePath();ctx.fill();}}}
</script><body><canvas id="canvas" style="border: 1px solid #999;" width="300" height="300"></canvas>
</body>
繪制文本
使用fillText()和strokeText()方法,可以分別以填充方式和輪廓方式繪制文本。
填充文字
fillText()方法能夠在畫布上繪制填色文本,默認顏色是黑色。其用法如下:
context
.fillText(text
, x
, y
, maxWidth
);
參數說明:
- text:規定在畫布上輸出的文本。
- x:開始繪制文本的x坐標位置(相對與畫布)。
- y:開始繪制文本的y坐標位置(相對與畫布)。
- maxWidth:可選參數,云溪的最大文本寬度,以像素計。
- 【實例】下面使用fillText()方法在畫布上繪制文本”Hi“和”佩琪鴿王!“。
<script>window.onload = function() {draw();function draw() {var ctx = document.getElementById("canvas").getContext('2d');ctx.font = "40px Georgia"ctx.fillText("Hi", 10, 50);ctx.font = "50px Verdana";var gradient = ctx.createLinearGradient(0, 0, canvas.width, 0);gradient.addColorStop("0", "magenta");gradient.addColorStop("0.5", "blue");gradient.addColorStop("1.0", "red");ctx.fillStyle = gradient;ctx.fillText("***!佩琪鴿王!", 10, 120);}}
</script><body><canvas id="canvas" style="border: 1px solid #999;" width="400" height="300"></canvas>
</body>
輪廓文字
使用strokeText()方法可以在畫布上繪制描邊文體,默認顏色是黑色。其用法如下:
context.strokeText(text, x, y, maxWidth);
參數說明:
<script>window.onload = function() {draw();function draw() {var ctx = document.getElementById("canvas").getContext('2d');ctx.font = "40px Georgia"ctx.fillText("Hi", 10, 50);ctx.font = "50px Verdana";var gradient = ctx.createLinearGradient(0, 0, canvas.width, 0);gradient.addColorStop("0", "magenta");gradient.addColorStop("0.5", "blue");gradient.addColorStop("1.0", "red");ctx.stokeStyle = gradient;ctx.strokeText("Canvas API", 10, 120);}}
</script><body><canvas id="canvas" style="border: 1px solid #999;" width="400" height="300"></canvas>
</body>
文本樣式
下面簡單介紹文本樣式的相關屬性。
- font:定義字體樣式,語法與CSS字體樣式相同。默認字體樣式為10px sans-serif。
- textAlign:設置正在繪制的文本水平對齊方式,取值說明如下。
- start:默認值,文本在指定的位置開始。
- end:文本在指定的位置結束。
- center:文本的中心被放置在指定的位置。
- left:文本左對齊。
- right:文本右對齊。
- textBaseline:設置正在繪制的文本基線對齊方式,即文本垂直對齊方式,取值說明如下。
- alphabetic:默認值,文本基線是普通的子母基線。
- top:文本基線是en方框的頂端。
- hanging:文本基線是懸掛基線。
- middle:文本基線是em方框的正中間。
- ideographic:文本基線是表意基線。
- bottom:文本基線是em方框的底端。
- direction:設置文本方向,取值說明如下。
- ltr:從左到右。
- rtl:從右到左。
- inherit:默認值,繼承文本方向。
- 【實例1】下面實例在x軸150px的位置創建一條豎線,位置150就被定義為所有文本的錨點。然后比較每種textAlign屬性值對齊效果。
<script>window.onload = function() {draw();function draw() {var ctx = document.getElementById("canvas").getContext('2d');ctx.strokeStyle = "blue";ctx.moveTo(150, 20);ctx.lineTo(150, 170);ctx.stroke();ctx.font = "15px Arial";ctx.textAlign = "start";ctx.fillText("textAlign = start", 150, 60);ctx.textAlign = "end";ctx.fillText("textAlign = end", 150, 80);ctx.textAlign = "left";ctx.fillText("textAlign = left", 150, 100);ctx.textAlign = "center";ctx.fillText("textAlign = center", 150, 120);ctx.textAlign = "rigth";ctx.fillText("textAlign = right", 150, 140);}}
</script><body><canvas id="canvas" style="border: 1px solid #999;" width="400" height="300"></canvas>
</body>
- 【實例2】下面實例在y軸100px的位置創建一條水平線。位置100被定義為藍色填充,然后比較每種textBaseline屬性值對齊效果。
<script>window.onload = function() {draw();function draw() {var ctx = document.getElementById("canvas").getContext('2d');ctx.strokeStyle = "blue";ctx.moveTo(5, 100);ctx.lineTo(395, 100);ctx.stroke();ctx.font = "20px Arial";ctx.textBaseline = "top";ctx.fillText("Top", 5, 100);ctx.textBaseline = "bottom";ctx.fillText("Bottom", 50, 100);ctx.textBaseline = "middle";ctx.fillText("Middle", 120, 100);ctx.textBaseline = "alphabetic";ctx.fillText("Alphabetic", 190, 100);ctx.textBaseline = "hanging";ctx.fillText("Hangin", 290, 100);}}
</script><body><canvas id="canvas" style="border: 1px solid #999;" width="400" height="300"></canvas>
</body>
測量寬度
使用measureText()方法可以測量當前所繪制文字中指定文字的寬度,它返回一個TextMetrics對象,使用該對象的width屬性可以得到指定文字參數后所有繪制文字的總寬度。用法如下:
metrics
= context
.measureText(text
);
其中的參數text為要繪制的文字。
<script>window.onload = function() {draw();function draw() {var ctx = document.getElementById("canvas").getContext('2d');ctx.font = "blod 20px 楷體";ctx.fillStyle = "Blue";var txt1 = "HTML5 + CSS3";ctx.fillText(txt1, 10, 40);var txt2 = "以上字符串的寬度為:";var mtxt1 = ctx.measureText(txt1);var mtxt2 = ctx.measureText(txt2);ctx.font = "blod 15px 宋體";ctx.fillStyle = "Red";ctx.fillText(txt2, 10, 80);ctx.fillText(mtxt1.width, mtxt2.width, 80);}}
</script><body><canvas id="canvas" style="border: 1px solid #999;" width="400" height="300"></canvas>
</body>
在canvas中可以導入圖像。導入的圖像可以改變大小、裁切或合成。canvas支持多種圖像格式,如PNG、GIF、JPEG等。
導入圖像
在canvas中導入圖像的步驟如下。
確定圖像來源有以下4種方式,用戶可以任選一種。
- 頁面內的圖片:如果已知圖片元素的ID,則可以通過document.images集合、document.getElementByTagName()或document.getElementById()等方法獲取頁面的圖片元素。
- 其他canvas元素:可以通過document.getElmentByTagName()或document.getElementById()等方法獲取已經設計好的canvas元素。例如,可以使用這種方法作為一個比較大的canvas生成縮略圖。
- 用腳本創建一個新的Image對象:使用腳本可以從零點開始創建一個新的Image對象。不過這種方法存在一種缺點:如果圖像文件來源于網絡且較大,則會花費較長時間來裝載。所以如果不希望因為圖像文件裝載時間過長而等待,就需要做好預裝載的工作。
- 使用data:url方式引用圖像:這種方法允許用Base64編碼的字符串來定義一個圖片;優點是圖片可以即使使用,不必等待裝載,而且遷移也非常容易;缺點是無法緩存圖像,所以如果圖片較大,則不太合適這種方法,因為這會導致嵌入的url數據相當龐大。
使用腳本創建image對象時,其方法如下:
var img
= new Image();
img
.src
= 'image1.png';
如果要解決圖片預裝載問題,可以使用onload事件一邊裝載一邊繪制圖像函數。
var img
= new Image();
img
.onload = function(){}
img
.src
= 'image1.png';
不管采用什么方法獲取圖像資源,之后的工作都是使用drawImage()方法將圖像繪制到canvas中,drawImage()方法能夠在畫布上繪制圖像、畫布或視頻。該方法也能夠繪制圖像的某些部分,以及增加或減小圖像的尺寸。用法如下:
context
.drawImage(img
, x
, y
);
context
.drawImage(img
, x
, y
, width
, height
);
context
.drawImage(img
, sx
, sy
, swidth
, sheight
, x
, y
, width
, height
);
參數說明:
-
img:規定要使用的圖像、畫布或視頻。
-
sx:可選。開始剪切的x坐標位置。
-
sy:可選。開始剪切的y坐標位置。
-
swidth:可選。被剪切圖像的寬度。
-
sheight:可選。被剪切圖像的高度。
-
x:在畫布上放置圖像的x坐標位置。
-
y:在畫布上放置圖像的y坐標位置。
-
width:可選。要使用的圖像的寬度,可以實現伸展或縮小圖像。
-
height:可選。要使用的圖像的高度,可以實現伸展或縮小圖像。
-
【實例】下面實例演示了如何使用上述步驟將圖像引入canvas中。
<script>window.onload = function() {draw();function draw() {var ctx = document.getElementById("canvas").getContext('2d');var img = new Image();img.onload = function() {ctx.drawImage(img, 0, 0);}img.src = '../img/doge.jpg'}}
</script><body><canvas id="canvas" style="border: 1px solid #999;" width="400" height="300"></canvas>
</body>
縮放圖像
drawImage()方法的第2種方法可以用于使用圖片按指定的大小顯示。
context
.drawImage(image
, x
, y
, width
, height
);
其中width和height分別是圖像在canvas中顯示的寬度和高度。
<script>window.onload = function() {draw();function draw() {var ctx = document.getElementById("canvas").getContext('2d');var img = new Image();img.onload = function() {ctx.drawImage(img, 0, 0, 400, 300);}img.src = '../img/doge.jpg'}}
</script><body><canvas id="canvas" style="border: 1px solid #999;" width="400" height="300"></canvas>
</body>
裁切圖像
drawImage()的第三種方法用于創建圖像切片。用法如下:
context
.drawImage(image
, sx
, sy
, sw
, sh
, dx
, dy
, dw
, dh
);
sx、sy為原圖像被切割區域,sw、sh為原圖像被切下來的寬度和高度;dx、dy為被切割下來的原圖像要方式到的位置,dw、dh為被切割下來的圖像的寬度和高度。
<script>window.onload = function() {draw();function draw() {var ctx = document.getElementById("canvas").getContext('2d');var img = new Image();img.onload = function() {ctx.drawImage(img, 0, 0, 200, 150, 50, 50, 100, 50);}img.src = '../img/doge.jpg'}}
</script><body><canvas id="canvas" style="border: 1px solid #999;" width="400" height="300"></canvas>
</body>
平鋪圖像
圖像平鋪就是讓圖像鋪滿畫布,有兩種方法可以實現,下面結合實例進行說明。
- 【實例1】第一種方法是使用drawImage()方法。
<script>window.onload = function() {draw();function draw() {var ctx = document.getElementById("canvas").getContext('2d');var image = new Image();image.src = '../img/doge.jpg';image.onload = function() {var scale = 5;var n1 = image.width / scale;var n2 = image.heigth / scale;var n3 = canvas.width / n1;var n4 = canvas.height / n2;for (var i = 0; i < n3; i++) {for (var j = 0; j < n4; j++) {ctx.drawImage(image, i * n1, j * n2, n1, n2);}}}}}
</script><body><canvas id="canvas" style="border: 1px solid #999;" width="400" height="300"></canvas>
</body>
- 【實例2】使用createPattern()方法,該方法只用了幾個參數。
context.createPattern(image, type);
參數image為要平鋪的圖像,參數type必須是下面的字符串之一。
- no-repeat:不平鋪。
- repeat-x:橫方向平鋪。
- repeat-y:縱方向平鋪。
- repeat:全方向平鋪。
<script>window.onload = function() {draw();function draw() {var ctx = document.getElementById("canvas").getContext('2d');var image = new Image();image.src = '../img/doge.jpg';image.onload = function() {var ptrn = ctx.createPattern(image, 'repeat');ctx.fillStyle = ptrn;ctx.fillRect(0, 0, 400, 300);}}}
</script><body><canvas id="canvas" style="border: 1px solid #999;" width="400" height="300"></canvas>
</body>
?
總結
以上是生活随笔為你收集整理的js绘图的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。