<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
canvas {
border: 1px solid #ccc;
/*不建議在 樣式設置尺寸*/
/*width: 600px;
height: 400px;*/
}
</style>
</head>
<body>
<!--1.准備畫布-->
<!--1.1 畫布是白色的 而且默認300*150-->
<!--1.2 設置畫布的大小 width="600" height="400" -->
<canvas width="600" height="400"></canvas>
<!--2.准備繪制工具-->
<!--3.利用工具繪圖-->
<script>
/*1.獲取元素*/
var myCanvas = document.querySelector('canvas');
/*2.獲取上下文 繪制工具箱 */
/*是否有3d 暫時沒有*/
var ctx = myCanvas.getContext('2d'); /*web gl 繪制3d效果的網頁技術*/
/*3.移動畫筆*/
ctx.moveTo(100, 100);
/*4.繪制直線 (軌跡,繪制路徑)*/
ctx.lineTo(200, 100);
/*5.描邊*/
ctx.stroke();
</script>
</body>
</html>
什么是Canvas?
HTML5 的 canvas 元素使用 JavaScript 在網頁上繪制圖像。
畫布是一個矩形區域,您可以控制其每一像素。
canvas 擁有多種繪制路徑、矩形、圓形、字符以及添加圖像的方法。
創建Canvas元素
向 HTML5 頁面添加 canvas 元素。
規定元素的 id、寬度和高度:
<canvas id="myCanvas" width="200" height="100"></canvas>
/*獲取元素*/
var myCanvas = document.querySelector('#myCanvas');
/*獲取繪圖工具*/
var context = myCanvas.getContext('2d');
/*設置繪圖的起始位置*/
context.moveTo(100,100);
/*繪制路徑*/
context.lineTo(200,200);
/*描邊*/
context.stroke();
Canvas的基本使用
圖形繪制
需要理解些概念:
圖形繪制
需要理解些概念:
路徑的概念
路徑的繪制
路徑的繪制
描邊 stroke()
填充 fill()
填充 fill()

閉合路徑
手動閉合
程序閉合 closePath()
程序閉合 closePath()
填充規則(非零環繞)

開啟新的路徑 beginPath()
設置樣式
畫筆的狀態
lineWidth 線寬,默認1px
lineCap 線末端類型:(butt默認)、round、square
lineJoin 相交線的拐點 miter(默認)、round、bevel
strokeStyle 線的顏色
fillStyle 填充顏色
setLineDash() 設置虛線
getLineDash() 獲取虛線寬度集合
lineDashOffset 設置虛線偏移量(負值向右偏移)
lineCap 線末端類型:(butt默認)、round、square
lineJoin 相交線的拐點 miter(默認)、round、bevel
strokeStyle 線的顏色
fillStyle 填充顏色
setLineDash() 設置虛線
getLineDash() 獲取虛線寬度集合
lineDashOffset 設置虛線偏移量(負值向右偏移)
實例練習
繪制平行線
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> canvas { border: 1px solid #ccc; } </style> </head> <body> <canvas width="600" height="400"></canvas> <script> var myCanvas = document.querySelector('canvas'); var ctx = myCanvas.getContext('2d'); /*畫平行線*/ ctx.moveTo(100, 100.5); ctx.lineTo(300, 100.5); ctx.moveTo(100, 200); ctx.lineTo(300, 200); /*描邊*/ ctx.stroke(); /*關於線條的問題*/ /*1.默認的寬度是多少 1px*/ /*2.默認的顏色是什么 黑色*/ /*產生原因 對齊的點是線的中心位置 會把線分成兩個0.5px 顯示的是會不飽和增加寬度*/ /*解決方案 前后移動0.5px */ </script> </body> </html>

繪制三條不同顏色和寬度的平行線
ctx.textAlign文本水平對齊方式,相對繪制坐標來說的
ctx.direction屬性css(rtl ltr) start和end於此相關
ctx.textBaseline 設置基線(垂直對齊方式 )
measureText() 獲取文本寬度obj.width
五個參數drawImage(img,x,y,w,h)
九個參數drawImage(img,x,y,w,h,x1,y1,w1,h1)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> canvas { border: 1px solid #ccc; } </style> </head> <body> <canvas width="600" height="400"></canvas> <script> var myCanvas = document.querySelector('canvas'); var ctx = myCanvas.getContext('2d'); /*畫平行線*/ ctx.beginPath(); /*Kai*/ /*藍色 10px*/ ctx.moveTo(100, 100); ctx.lineTo(300, 100); ctx.strokeStyle = 'blue'; ctx.lineWidth = 10; /*描邊*/ ctx.stroke(); /*紅色 20px*/ ctx.moveTo(100, 200); ctx.lineTo(300, 200); ctx.strokeStyle = 'red'; ctx.lineWidth = 20; /*描邊*/ ctx.stroke(); /*綠色 30px*/ ctx.moveTo(100, 300); ctx.lineTo(300, 300); ctx.strokeStyle = 'green'; ctx.lineWidth = 30; /*描邊*/ ctx.stroke(); </script> </body> </html>
繪制一個填充的三角形
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> canvas { border: 1px solid #ccc; } </style> </head> <body> <canvas width="600" height="400"></canvas> <script> var myCanvas = document.querySelector('canvas'); var ctx = myCanvas.getContext('2d'); /*1.繪制一個三角形*/ ctx.moveTo(100, 100); ctx.lineTo(200, 100); ctx.lineTo(200, 200); /*起始點和lineTo的結束點無法完全閉合缺角*/ /*使用canvas的自動閉合 */ //ctx.lineTo(100,100); /*關閉路徑*/ ctx.closePath(); ctx.lineWidth = 10; /*2.描邊*/ ctx.stroke(); /*3.填充*/ //ctx.fill(); </script> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> canvas { border: 1px solid #ccc; } </style> </head> <body> <canvas width="600" height="400"></canvas> <script> var myCanvas = document.querySelector('canvas'); var ctx = myCanvas.getContext('2d'); /*1.繪制兩個正方形 一大200一小100 套在一起*/ ctx.moveTo(100, 100); ctx.lineTo(300, 100); ctx.lineTo(300, 300); ctx.lineTo(100, 300); ctx.closePath(); ctx.moveTo(150, 150); ctx.lineTo(150, 250); ctx.lineTo(250, 250); ctx.lineTo(250, 150); ctx.closePath(); /*2.去填充*/ //ctx.stroke(); ctx.fillStyle = 'red'; ctx.fill(); /*在填充的時候回遵循非零環繞規則*/ </script> </body> </html>
和線相關屬性方法
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> canvas { border: 1px solid #ccc; } </style> </head> <body> <canvas width="600" height="400"></canvas> <script> var myCanvas = document.querySelector('canvas'); var ctx = myCanvas.getContext('2d'); /*畫平行線*/ ctx.beginPath(); ctx.moveTo(100, 100); ctx.lineTo(200, 20); ctx.lineTo(300, 100); ctx.strokeStyle = 'blue'; ctx.lineWidth = 10; ctx.lineCap = 'butt'; ctx.lineJoin = 'miter'; ctx.stroke(); ctx.beginPath(); ctx.moveTo(100, 200); ctx.lineTo(200, 120); ctx.lineTo(300, 200); ctx.strokeStyle = 'red'; ctx.lineWidth = 20; ctx.lineCap = 'square'; ctx.lineJoin = 'bevel'; ctx.stroke(); ctx.beginPath(); ctx.moveTo(100, 300); ctx.lineTo(200, 220); ctx.lineTo(300, 300); ctx.strokeStyle = 'green'; ctx.lineWidth = 30; ctx.lineCap = 'round'; ctx.lineJoin = 'round'; ctx.stroke(); </script> </body> </html>
繪制虛線
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> canvas { border: 1px solid #ccc; } </style> </head> <body> <canvas width="600" height="400"></canvas> <script> var myCanvas = document.querySelector('canvas'); var ctx = myCanvas.getContext('2d'); /*畫線*/ ctx.moveTo(100, 100.5); ctx.lineTo(300, 100.5); /*[5,10] 數組是用來描述你的排列方式的*/ ctx.setLineDash([20]); /*獲取虛線的排列方式 獲取的是不重復的那一段的排列方式*/ console.log(ctx.getLineDash()); /*如果是正的值 往后偏移*/ /*如果是負的值 往前偏移*/ ctx.lineDashOffset = -20; ctx.stroke(); </script> </body> </html>
漸變色繪制
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> canvas { border: 1px solid #ccc; } </style> </head> <body> <canvas width="600" height="400"></canvas> <script> var myCanvas = document.querySelector('canvas'); var ctx = myCanvas.getContext('2d'); /*繪制一個矩形*/ /*線是由點構成的*/ /*ctx.moveTo(100,100); ctx.lineTo(355,100); ctx.lineWidth = 30;*/ /*顏色的填充*/ //ctx.strokeStyle = '#fff'; /*黑到白的漸變顏色*/ /* ctx.stroke();*/ /*線是由點構成的*/ ctx.lineWidth = 30; for (var i = 0; i < 255; i++) { ctx.beginPath(); ctx.moveTo(100 + i - 1, 100); ctx.lineTo(100 + i, 100); ctx.strokeStyle = 'rgb(' + i + ',0,0)'; ctx.stroke(); } </script> </body> </html>
- 鏤空的房子
- 繪制坐標網格
-
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> canvas { border: 1px solid #ccc; } </style> </head> <body> <canvas width="600" height="400"></canvas> <script> var myCanvas = document.querySelector('canvas'); var ctx = myCanvas.getContext('2d'); /*1.繪制網格*/ /*2.網格的大小*/ var gridSize = 10; var canvasHeight = ctx.canvas.height; var canvasWidth = ctx.canvas.width; /*3.畫多少條X軸方向的線 橫線的條數 畫布高度*/ /*var canvasHeight = myCanvas.height; var canvasWidth = myCanvas.width; console.log(canvasHeight); console.log(canvasWidth);*/ /*console.log(ctx.canvas.width); console.log(ctx.canvas.height);*/ var xLineTotal = Math.floor(canvasHeight / gridSize); for (var i = 0; i <= xLineTotal; i++) { ctx.beginPath(); ctx.moveTo(0, i * gridSize - 0.5); ctx.lineTo(canvasWidth, i * gridSize - 0.5); ctx.strokeStyle = '#eee'; ctx.stroke(); } /*4.畫多少條Y軸方向的線*/ var yLineTotal = Math.floor(canvasWidth / gridSize); for (var i = 0; i <= yLineTotal; i++) { ctx.beginPath(); ctx.moveTo(i * gridSize - 0.5, 0); ctx.lineTo(i * gridSize - 0.5, canvasHeight); ctx.strokeStyle = '#eee'; ctx.stroke(); } /*5.遍歷的形式去畫*/ </script> </body> </html>
-
繪制坐標系
-
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> canvas { border: 1px solid #ccc; } </style> </head> <body> <canvas width="600" height="400"></canvas> <script> var myCanvas = document.querySelector('canvas'); var ctx = myCanvas.getContext('2d'); /*1.繪制坐標系*/ /*2.確定原點*/ /*3.確定距離畫布旁邊的距離*/ /*4.確定坐標軸的長度*/ /*5.確定箭頭的大小 是個等腰三角形 10 */ /*6.繪制箭頭填充*/ var space = 20; var arrowSize = 10; /*計算原點*/ var canvasWidth = ctx.canvas.width; var canvasHeight = ctx.canvas.height; var x0 = space; var y0 = canvasHeight - space; /*繪制x軸*/ ctx.beginPath(); ctx.moveTo(x0, y0); ctx.lineTo(canvasWidth - space, y0); /*箭頭*/ ctx.lineTo(canvasWidth - space - arrowSize, y0 + arrowSize / 2); ctx.lineTo(canvasWidth - space - arrowSize, y0 - arrowSize / 2); ctx.lineTo(canvasWidth - space, y0); ctx.fill(); ctx.stroke(); /*繪制y軸*/ ctx.beginPath(); ctx.moveTo(x0, y0); ctx.lineTo(space, space); /*箭頭*/ ctx.lineTo(space + arrowSize / 2, space + arrowSize); ctx.lineTo(space - arrowSize / 2, space + arrowSize); ctx.lineTo(space, space); ctx.fill(); ctx.stroke(); </script> </body> </html>
- 繪制坐標點
-
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> canvas { border: 1px solid #ccc; } </style> </head> <body> <canvas width="600" height="400"></canvas> <script> var myCanvas = document.querySelector('canvas'); var ctx = myCanvas.getContext('2d'); /*1.繪制點*/ /*2.點的尺寸*/ /*3.以坐標中心繪制點*/ /*點坐標*/ var coordinate = { x: 100, y: 100 } /*點尺寸*/ var dottedSize = 10; ctx.moveTo(coordinate.x - dottedSize / 2, coordinate.y - dottedSize / 2); ctx.lineTo(coordinate.x + dottedSize / 2, coordinate.y - dottedSize / 2); ctx.lineTo(coordinate.x + dottedSize / 2, coordinate.y + dottedSize / 2); ctx.lineTo(coordinate.x - dottedSize / 2, coordinate.y + dottedSize / 2); ctx.closePath(); ctx.fill(); </script> </body> </html>
-
繪制折線圖
-
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> canvas { border: 1px solid #ccc; } </style> </head> <body> <canvas width="600" height="400"></canvas> <script> /*1.構造函數*/ var LineChart = function (ctx) { /*獲取繪圖工具*/ this.ctx = ctx || document.querySelector('canvas').getContext('2d'); /*畫布的大小*/ this.canvasWidth = this.ctx.canvas.width; this.canvasHeight = this.ctx.canvas.height; /*網格的大小*/ this.gridSize = 10; /*坐標系的間距*/ this.space = 20; /*坐標原點*/ this.x0 = this.space; this.y0 = this.canvasHeight - this.space; /*箭頭的大小*/ this.arrowSize = 10; /*繪制點*/ this.dottedSize = 6; /*點的坐標 和數據有關系 數據可視化*/ } /*2.行為方法*/ LineChart.prototype.init = function (data) { this.drawGrid(); this.drawAxis(); this.drawDotted(data); }; /*繪制網格*/ LineChart.prototype.drawGrid = function () { /*x方向的線*/ var xLineTotal = Math.floor(this.canvasHeight / this.gridSize); this.ctx.strokeStyle = '#eee'; for (var i = 0; i <= xLineTotal; i++) { this.ctx.beginPath(); this.ctx.moveTo(0, i * this.gridSize - 0.5); this.ctx.lineTo(this.canvasWidth, i * this.gridSize - 0.5); this.ctx.stroke(); } /*y方向的線*/ var yLineTotal = Math.floor(this.canvasWidth / this.gridSize); for (var i = 0; i <= yLineTotal; i++) { this.ctx.beginPath(); this.ctx.moveTo(i * this.gridSize - 0.5, 0); this.ctx.lineTo(i * this.gridSize - 0.5, this.canvasHeight); this.ctx.stroke(); } }; /*繪制坐標系*/ LineChart.prototype.drawAxis = function () { /*X軸*/ this.ctx.beginPath(); this.ctx.strokeStyle = '#000'; this.ctx.moveTo(this.x0, this.y0); this.ctx.lineTo(this.canvasWidth - this.space, this.y0); this.ctx.lineTo(this.canvasWidth - this.space - this.arrowSize, this.y0 + this.arrowSize / 2); this.ctx.lineTo(this.canvasWidth - this.space - this.arrowSize, this.y0 - this.arrowSize / 2); this.ctx.lineTo(this.canvasWidth - this.space, this.y0); this.ctx.stroke(); this.ctx.fill(); /*Y軸*/ this.ctx.beginPath(); this.ctx.strokeStyle = '#000'; this.ctx.moveTo(this.x0, this.y0); this.ctx.lineTo(this.space, this.space); this.ctx.lineTo(this.space + this.arrowSize / 2, this.space + this.arrowSize); this.ctx.lineTo(this.space - this.arrowSize / 2, this.space + this.arrowSize); this.ctx.lineTo(this.space, this.space); this.ctx.stroke(); this.ctx.fill(); }; /*繪制所有點*/ LineChart.prototype.drawDotted = function (data) { /*1.數據的坐標 需要轉換 canvas坐標*/ /*2.再進行點的繪制*/ /*3.把線連起來*/ var that = this; /*記錄當前坐標*/ var prevCanvasX = 0; var prevCanvasY = 0; data.forEach(function (item, i) { /* x = 原點的坐標 + 數據的坐標 */ /* y = 原點的坐標 - 數據的坐標 */ var canvasX = that.x0 + item.x; var canvasY = that.y0 - item.y; /*繪制點*/ that.ctx.beginPath(); that.ctx.moveTo(canvasX - that.dottedSize / 2, canvasY - that.dottedSize / 2); that.ctx.lineTo(canvasX + that.dottedSize / 2, canvasY - that.dottedSize / 2); that.ctx.lineTo(canvasX + that.dottedSize / 2, canvasY + that.dottedSize / 2); that.ctx.lineTo(canvasX - that.dottedSize / 2, canvasY + that.dottedSize / 2); that.ctx.closePath(); that.ctx.fill(); /*點的連線*/ /*當時第一個點的時候 起點是 x0 y0*/ /*當時不是第一個點的時候 起點是 上一個點*/ if (i == 0) { that.ctx.beginPath(); that.ctx.moveTo(that.x0, that.y0); that.ctx.lineTo(canvasX, canvasY); that.ctx.stroke(); } else { /*上一個點*/ that.ctx.beginPath(); that.ctx.moveTo(prevCanvasX, prevCanvasY); that.ctx.lineTo(canvasX, canvasY); that.ctx.stroke(); } /*記錄當前的坐標,下一次要用*/ prevCanvasX = canvasX; prevCanvasY = canvasY; }); }; /*3.初始化*/ var data = [{ x: 100, y: 120 }, { x: 200, y: 160 }, { x: 300, y: 240 }, { x: 400, y: 120 }, { x: 500, y: 80 } ]; var lineChart = new LineChart(); lineChart.init(data); </script> </body> </html>
-
參考文檔w3school
Canvas_APICanvas圖形繪制
矩形繪制rect(x,y,w,h) 沒有獨立路徑
strokeRect(x,y,w,h) 有獨立路徑,不影響別的繪制
fillRect(x,y,w,h) 有獨立路徑,不影響別的繪制
clearRect(x,y,w,h) 擦除矩形區域 - 繪制顏色漸變的矩形
-
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> canvas { border: 1px solid #ccc; } /* .linearGradient{ width: 400px; height: 100px; background-image: linear-gradient(to right,pink,blue); }*/ </style> </head> <body> <div class="linearGradient"></div> <canvas width="600" height="400"></canvas> <script> var myCanvas = document.querySelector('canvas'); var ctx = myCanvas.getContext('2d'); /*fillStyle 'pink' '#000' 'rgb()' 'rgba()' */ /*也可以使用一個漸變的方案了填充矩形*/ /*創建一個漸變的方案*/ /*漸變是由長度的*/ /*x0y0 起始點 x1y1 結束點 確定長度和方向*/ var linearGradient = ctx.createLinearGradient(100, 100, 500, 400); linearGradient.addColorStop(0, 'pink'); //linearGradient.addColorStop(0.5,'red'); linearGradient.addColorStop(1, 'blue'); ctx.fillStyle = linearGradient; ctx.fillRect(100, 100, 400, 100); /*pink---->blue*/ /*回想線性漸變---->要素 方向 起始顏色 結束顏色 */ /*通過兩個點的坐標可以控制 漸變方向*/ </script> </body> </html>
-
圓弧繪制
- 弧度概念
- arc()
- x 圓心橫坐標
- y 圓心縱坐標
- r 半徑
- startAngle 開始角度
- endAngle 結束角度
- anticlockwise 是否逆時針方向繪制(默認false表示順時針;true表示逆時針)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> canvas { border: 1px solid #ccc; } </style> </head> <body> <canvas width="600" height="400"></canvas> <script> var myCanvas = document.querySelector('canvas'); var ctx = myCanvas.getContext('2d'); /*1.體驗曲線的繪制*/ /*2.線是由點構成的*/ /*3.曲線可以由數學公式得來*/ /*公式:y = x/2 */ /*公式:y = (x + 2) ^2 */ /*公式:y = sin(x) */ for (var i = 1; i < 600; i++) { var x = i; //var y = x/2; //var y = Math.pow(x/10-30,2); var y = 50 * Math.sin(x / 10) + 100; ctx.lineTo(x, y); } ctx.stroke(); </script> </body> </html>
繪制文本
ctx.font = ‘微軟雅黑’ 設置字體
strokeText()
fillText(text,x,y,maxWidth)
strokeText()
fillText(text,x,y,maxWidth)
text 要繪制的文本
x,y 文本繪制的坐標(文本左下角)
maxWidth 設置文本最大寬度,可選參數
x,y 文本繪制的坐標(文本左下角)
maxWidth 設置文本最大寬度,可選參數
ctx.textAlign文本水平對齊方式,相對繪制坐標來說的
left
center
right
start 默認
end
center
right
start 默認
end
ctx.direction屬性css(rtl ltr) start和end於此相關
如果是ltr,start和left表現一致
如果是rtl,start和right表現一致
如果是rtl,start和right表現一致
ctx.textBaseline 設置基線(垂直對齊方式 )
top 文本的基線處於文本的正上方,並且有一段距離
middle 文本的基線處於文本的正中間
bottom 文本的基線處於文本的證下方,並且有一段距離
hanging 文本的基線處於文本的正上方,並且和文本粘合
alphabetic 默認值,基線處於文本的下方,並且穿過文字
ideographic 和bottom相似,但是不一樣
middle 文本的基線處於文本的正中間
bottom 文本的基線處於文本的證下方,並且有一段距離
hanging 文本的基線處於文本的正上方,並且和文本粘合
alphabetic 默認值,基線處於文本的下方,並且穿過文字
ideographic 和bottom相似,但是不一樣
measureText() 獲取文本寬度obj.width
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> canvas { border: 1px solid #ccc; display: block; margin: 100px auto; } </style> </head> <body> <canvas width="600" height="400"></canvas> <script> var myCanvas = document.querySelector('canvas'); var ctx = myCanvas.getContext('2d'); /*1.在畫布的中心繪制一段文字*/ /*2.申明一段文字*/ var str = '您吃-,了嗎'; /*3.確定畫布的中心*/ var w = ctx.canvas.width; var h = ctx.canvas.height; /*4.畫一個十字架在畫布的中心*/ ctx.beginPath(); ctx.moveTo(0, h / 2 - 0.5); ctx.lineTo(w, h / 2 - 0.5); ctx.moveTo(w / 2 - 0.5, 0); ctx.lineTo(w / 2 - 0.5, h); ctx.strokeStyle = '#eee'; ctx.stroke(); /*5.繪制文本*/ ctx.beginPath(); ctx.strokeStyle = '#000'; var x0 = w / 2; var y0 = h / 2; /*注意:起點位置在文字的左下角*/ /*有文本的屬性 尺寸 字體 左右對齊方式 垂直對齊的方式*/ ctx.font = '40px Microsoft YaHei'; /*左右對齊方式 (center left right start end) 基准起始坐標*/ ctx.textAlign = 'center'; /*垂直對齊的方式 基線 baseline(top,bottom,middle) 基准起始坐標*/ ctx.textBaseline = 'middle'; //ctx.direction = 'rtl'; //ctx.strokeText(str,x0,y0); ctx.fillText(str, x0, y0); /*6.畫一個下划線和文字一樣長*/ ctx.beginPath(); /*獲取文本的寬度*/ console.log(ctx.measureText(str)); var width = ctx.measureText(str).width; ctx.moveTo(x0 - width / 2, y0 + 20); ctx.lineTo(x0 + width / 2, y0 + 20); ctx.stroke(); </script> </body> </html>

實例練習
- 繪制圓弧
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> canvas { border: 1px solid #ccc; } </style> </head> <body> <canvas width="600" height="400"></canvas> <script> var myCanvas = document.querySelector('canvas'); var ctx = myCanvas.getContext('2d'); /*繪制圓弧*/ /*確定圓心 坐標 x y*/ /*確定圓半徑 r */ /*確定起始繪制的位置和結束繪制的位置 確定弧的長度和位置 startAngle endAngle 弧度*/ /*取得繪制的方向 direction 默認是順時針 false 逆時針 true */ /*在中心位置畫一個半徑150px的圓弧左下角*/ var w = ctx.canvas.width; var h = ctx.canvas.height; ctx.arc(w / 2, h / 2, 150, Math.PI / 2, Math.PI, true); ctx.stroke(); </script> </body> </html>
繪制扇形
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> canvas { border: 1px solid #ccc; } </style> </head> <body> <canvas width="600" height="400"></canvas> <script> var myCanvas = document.querySelector('canvas'); var ctx = myCanvas.getContext('2d'); /*在中心位置畫一個半徑150px的圓弧右上角 扇形 邊 填充 */ var w = ctx.canvas.width; var h = ctx.canvas.height; /*把起點放到圓心位置*/ ctx.moveTo(w / 2, h / 2); ctx.arc(w / 2, h / 2, 150, 0, -Math.PI / 2, true); /*閉合路徑*/ //ctx.closePath(); ctx.fill(); </script> </body> </html>
繪制一個圓分成六等分顏色隨機
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> canvas { border: 1px solid #ccc; } </style> </head> <body> <canvas width="600" height="400"></canvas> <script> var myCanvas = document.querySelector('canvas'); var ctx = myCanvas.getContext('2d'); var w = ctx.canvas.width; var h = ctx.canvas.height; /*分成幾等分*/ var num = 360; /*一份多少弧度*/ var angle = Math.PI * 2 / num; /*原點坐標*/ var x0 = w / 2; var y0 = h / 2; /*獲取隨機顏色*/ var getRandomColor = function () { var r = Math.floor(Math.random() * 256); var g = Math.floor(Math.random() * 256); var b = Math.floor(Math.random() * 256); return 'rgb(' + r + ',' + g + ',' + b + ')'; } /*上一次繪制的結束弧度等於當前次的起始弧度*/ //var startAngle = 0; for (var i = 0; i < num; i++) { var startAngle = i * angle; var endAngle = (i + 1) * angle; ctx.beginPath(); ctx.moveTo(x0, y0); ctx.arc(x0, y0, 150, startAngle, endAngle); /*隨機顏色*/ ctx.fillStyle = getRandomColor(); ctx.fill(); } </script> </body> </html>
繪制餅圖
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> canvas { border: 1px solid #ccc; display: block; margin: 100px auto; } </style> </head> <body> <canvas width="600" height="400"></canvas> <script> /*var myCanvas = document.querySelector('canvas'); var ctx = myCanvas.getContext('2d');*/ /*1.繪制餅狀態圖*/ /*1.1 根據數據繪制一個餅圖*/ /*1.2 繪制標題 從扇形的弧中心伸出一條線在畫一條橫線在橫線的上面寫上文字標題*/ /*1.3 在畫布的左上角 繪制說明 一個和扇形一樣顏色的矩形 旁邊就是文字說明*/ var PieChart = function (ctx) { /*繪制工具*/ this.ctx = ctx || document.querySelector('canvas').getContext('2d'); /*繪制餅圖的中心*/ this.w = this.ctx.canvas.width; this.h = this.ctx.canvas.height; /*圓心*/ this.x0 = this.w / 2 + 60; this.y0 = this.h / 2; /*半徑*/ this.radius = 150; /*伸出去的線的長度*/ this.outLine = 20; /*說明的矩形大小*/ this.rectW = 30; this.rectH = 16; this.space = 20; } PieChart.prototype.init = function (data) { /*1.准備數據*/ this.drawPie(data); }; PieChart.prototype.drawPie = function (data) { var that = this; /*1.轉化弧度*/ var angleList = this.transformAngle(data); /*2.繪制餅圖*/ var startAngle = 0; angleList.forEach(function (item, i) { /*當前的結束弧度要等於下一次的起始弧度*/ var endAngle = startAngle + item.angle; that.ctx.beginPath(); that.ctx.moveTo(that.x0, that.y0); that.ctx.arc(that.x0, that.y0, that.radius, startAngle, endAngle); var color = that.ctx.fillStyle = that.getRandomColor(); that.ctx.fill(); /*下一次要使用當前的這一次的結束角度*/ /*繪制標題*/ that.drawTitle(startAngle, item.angle, color, item.title); /*繪制說明*/ that.drawDesc(i, item.title); startAngle = endAngle; }); }; PieChart.prototype.drawTitle = function (startAngle, angle, color, title) { /*1.確定伸出去的線 通過圓心點 通過伸出去的點 確定這個線*/ /*2.確定伸出去的點 需要確定伸出去的線的長度*/ /*3.固定伸出去的線的長度*/ /*4.計算這個點的坐標*/ /*5.需要根據角度和斜邊的長度*/ /*5.1 使用弧度 當前扇形的起始弧度 + 對應的弧度的一半 */ /*5.2 半徑+伸出去的長度 */ /*5.3 outX = x0 + cos(angle) * ( r + outLine)*/ /*5.3 outY = y0 + sin(angle) * ( r + outLine)*/ /*斜邊*/ var edge = this.radius + this.outLine; /*x軸方向的直角邊*/ var edgeX = Math.cos(startAngle + angle / 2) * edge; /*y軸方向的直角邊*/ var edgeY = Math.sin(startAngle + angle / 2) * edge; /*計算出去的點坐標*/ var outX = this.x0 + edgeX; var outY = this.y0 + edgeY; this.ctx.beginPath(); this.ctx.moveTo(this.x0, this.y0); this.ctx.lineTo(outX, outY); this.ctx.strokeStyle = color; /*畫文字和下划線*/ /*線的方向怎么判斷 伸出去的點在X0的左邊 線的方向就是左邊*/ /*線的方向怎么判斷 伸出去的點在X0的右邊 線的方向就是右邊*/ /*結束的點坐標 和文字大小*/ this.ctx.font = '14px Microsoft YaHei'; var textWidth = this.ctx.measureText(title).width; if (outX > this.x0) { /*右*/ this.ctx.lineTo(outX + textWidth, outY); this.ctx.textAlign = 'left'; } else { /*左*/ this.ctx.lineTo(outX - textWidth, outY); this.ctx.textAlign = 'right'; } this.ctx.stroke(); this.ctx.textBaseline = 'bottom'; this.ctx.fillText(title, outX, outY); }; PieChart.prototype.drawDesc = function (index, title) { /*繪制說明*/ /*矩形的大小*/ /*距離上和左邊的間距*/ /*矩形之間的間距*/ this.ctx.fillRect(this.space, this.space + index * (this.rectH + 10), this.rectW, this.rectH); /*繪制文字*/ this.ctx.beginPath(); this.ctx.textAlign = 'left'; this.ctx.textBaseline = 'top'; this.ctx.font = '12px Microsoft YaHei'; this.ctx.fillText(title, this.space + this.rectW + 10, this.space + index * (this.rectH + 10)); }; PieChart.prototype.transformAngle = function (data) { /*返回的數據內容包含弧度的*/ var total = 0; data.forEach(function (item, i) { total += item.num; }); /*計算弧度 並且追加到當前的對象內容*/ data.forEach(function (item, i) { var angle = item.num / total * Math.PI * 2; item.angle = angle; }); return data; }; PieChart.prototype.getRandomColor = function () { var r = Math.floor(Math.random() * 256); var g = Math.floor(Math.random() * 256); var b = Math.floor(Math.random() * 256); return 'rgb(' + r + ',' + g + ',' + b + ')'; }; var data = [{ title: '15-20歲', num: 6 }, { title: '20-25歲', num: 30 }, { title: '25-30歲', num: 10 }, { title: '30以上', num: 8 } ]; var pieChart = new PieChart(); pieChart.init(data); </script> </body> </html>
做動畫
繪制圖片
繪制圖片
drawImage()
三個參數drawImage(img,x,y)
img 圖片對象、canvas對象、video對象
x,y 圖片繪制的左上角
x,y 圖片繪制的左上角
五個參數drawImage(img,x,y,w,h)
img 圖片對象、canvas對象、video對象
x,y 圖片繪制的左上角
w,h 圖片繪制尺寸設置(圖片縮放,不是截取)
x,y 圖片繪制的左上角
w,h 圖片繪制尺寸設置(圖片縮放,不是截取)
九個參數drawImage(img,x,y,w,h,x1,y1,w1,h1)
img 圖片對象、canvas對象、video對象
x,y,w,h 圖片中的一個矩形區域
x1,y1,w1,h1 畫布中的一個矩形區域
x,y,w,h 圖片中的一個矩形區域
x1,y1,w1,h1 畫布中的一個矩形區域
序列幀動畫
繪制精靈圖
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> canvas { border: 1px solid #ccc; } </style> </head> <body> <!--<img src="image/01.jpg" alt="">--> <canvas width="600" height="400"></canvas> <script> var myCanvas = document.querySelector('canvas'); var ctx = myCanvas.getContext('2d'); /*1.加載圖片到內存即可*/ /*var img = document.createElement('img'); img.src = 'image/01.jpg';*/ /*創建對象*/ var image = new Image(); /*綁定加載完成事件*/ image.onload = function () { /*實現圖片繪制*/ console.log(image); /*繪制圖片的三種方式*/ /*3參數*/ /*圖片對象*/ /*繪制在畫布上的坐標 x y*/ //ctx.drawImage(image,100,100); /*5個參數*/ /*圖片對象*/ /*繪制在畫布上的坐標 x y*/ /*是圖片的大小 不是裁剪 是縮放*/ //ctx.drawImage(image,100,100,100,100); /*9個參數*/ /*圖片對象*/ /*圖片上定位的坐標 x y */ /*在圖片上截取多大的區域 w h*/ /*繪制在畫布上的坐標 x y*/ /*是圖片的大小 不是裁剪 是縮放*/ ctx.drawImage(image, 400, 400, 400, 400, 200, 200, 100, 100); }; /*設置圖片路徑*/ image.src = 'image/02.jpg'; </script> </body> </html>