mdn 文檔javascript
canvas 能夠用於動畫、遊戲畫面、數據可視化、圖片編輯以及實時視頻處理等內容。html
canvas api 主要聚焦於 2D 圖形。java
WebGL api 主要聚焦於硬件加速的 2D 和 3D 圖形。canvas
先來看一個基礎事例:api
<canvas id="canvas">
Your browser not support canvas, please update browser.
</canvas>
<script> function draw() { // 獲取 canvas 元素 const canvas = document.getElementById('canvas'); // 建立畫板 const context = canvas.getContext('2d'); // 填充形狀 context.fillRect(10, 10, 55, 50); // 填充顏色 context.fillStyle = 'black'; } draw(); </script>
複製代碼
這時,瀏覽器會出現一個黑色的方塊:瀏覽器
首先學習如何繪製矩形。緩存
canvas 提供了 3 種方法來繪製矩形:微信
使用以上三個方法構建一個空心矩形:markdown
function draw() {
const canvas = document.getElementById('canvas');
const context = canvas.getContext('2d');
context.fillRect(25, 25, 100, 100);
context.clearRect(50, 50, 50, 50);
}
draw();
複製代碼
如圖下所示:svg
繪圖的基本元素是路徑。
路徑:經過不一樣顏色和寬度的線段或曲線相連造成的不一樣形狀的點的集合
一下是所須要的函數:
用以上的方法來構建一個矩形:
function draw() {
const canvas = document.getElementById('canvas');
const context = canvas.getContext('2d');
context.beginPath();
context.moveTo(100, 100);
context.lineTo(100, 0);
context.lineTo(0, 0);
context.lineTo(0, 100);
context.fill();
}
draw();
複製代碼
生成路徑:
beginPath(): 本質上,路徑是由不少子路徑構成,這些子路徑都是在一個列表中,全部的子路徑來構成圖形。每次調用這個方法,列表都會清空,而後就能夠從新繪製新的圖形了;
moveTo(): 設置路徑以後,指定起始位置;
lineTo(): 調用函數繪製路徑;
closePath(): 閉合路徑(非必需),在調用 fill() 函數時,全部沒有閉合的形狀都會自動閉合。
moveTo(): 從畫布上的一個點移動到另一個點。
使用 lineTo(x, y) 方法:從當前位置到 (x, y) 的指導位置的線段。
arc()
函數中,表示角度的單位是弧度,不是角度。角度轉弧度的公式爲:弧度 = 角度 * (π/ 180)
使用以上方法,畫一個實心圓:
function draw() {
const canvas = document.getElementById('canvas');
const context = canvas.getContext('2d');
context.beginPath();
context.moveTo(50, 50);
context.arc(50, 50, 25, 0, 2 * Math.PI, true);
context.fill();
}
draw();
複製代碼
如圖下所示:
爲了簡化代碼以及提升性能,咱們可使用 Path2D 用來緩存或者記錄繪畫命令。
來實驗一下,來畫一個內切圓:
function draw() {
const canvas = document.getElementById('canvas');
const context = canvas.getContext('2d');
const rectangle = new Path2D();
rectangle.rect(0, 0, 100, 100);
const circle = new Path2D();
circle.moveTo(50, 50);
circle.arc(50, 50, 50, 2 * Math.PI, false);
context.stroke(rectangle);
context.stroke(circle);
}
draw();
複製代碼
可使用 svg path data 來初始化 canvas 上面的路徑
到如今爲止,咱們可使用一系列路徑來將咱們所須要的圖形,繪畫在畫布上面了。大致上的步驟以下:
接下來,就經過上面學習到的知識來畫一個簡單的柱狀圖:
生成軸線:
// 座標軸生成
createAxle(type = 'x') {
const {point, axleLength} = this.defaults;
const axle = new Path2D();
axle.moveTo(...point);
if (type === 'x') {
axle.lineTo(point[0] + axleLength, point[1]);
} else {
axle.lineTo(point[0], point[1] - axleLength);
}
this.context.stroke(axle);
}
複製代碼
生成刻度:
// 生成刻度
createScale(type = 'x') {
const {point, count, axleLength, scaleLength} = this.defaults;
const ruleWidth = parseInt(axleLength / count, 10);
const scale = new Path2D();
for (let i = 0; i <= axleLength; i += ruleWidth) {
if (type === 'x') {
scale.moveTo(point[0] + i, point[1]);
scale.lineTo(point[0] + i, point[1] + scaleLength);
} else {
scale.moveTo(point[0], point[1] - i);
scale.lineTo(point[0] - scaleLength, point[1] - i);
}
}
this.context.stroke(scale);
}
複製代碼
最後一步,咱們就要畫出柱狀圖的關鍵,柱子了。
// 畫柱狀圖
createRect() {
const {point, axleLength, count} = this.defaults;
const rectLength = parseInt(axleLength / count, 10);
const rect = new Path2D();
for (let i = 0; i <= count; i += 1) {
rect.rect(
point[0] + (rectLength * i),
point[1],
rectLength,
-rectLength * i
);
}
this.context.fill(rect);
}
複製代碼
class LineChart {
constructor(config) {
const canvas = document.getElementById('canvas');
this.context = canvas.getContext('2d');
this.defaults = {
point: [50, 120],
axleLength: 100,
count: 5,
scaleLength: 5
};
Object.assign(this.defaults, config);
}
// 座標軸生成
createAxle(type = 'x') {
const {point, axleLength} = this.defaults;
const axle = new Path2D();
axle.moveTo(...point);
if (type === 'x') {
axle.lineTo(point[0] + axleLength, point[1]);
} else {
axle.lineTo(point[0], point[1] - axleLength);
}
this.context.stroke(axle);
}
// 座標標尺
createScale(type = 'x') {
const {point, count, axleLength, scaleLength} = this.defaults;
const ruleWidth = parseInt(axleLength / count, 10);
const scale = new Path2D();
for (let i = 0; i <= axleLength; i += ruleWidth) {
if (type === 'x') {
scale.moveTo(point[0] + i, point[1]);
scale.lineTo(point[0] + i, point[1] + scaleLength);
} else {
scale.moveTo(point[0], point[1] - i);
scale.lineTo(point[0] - scaleLength, point[1] - i);
}
}
this.context.stroke(scale);
}
// 畫柱狀圖
createRect() {
const {point, axleLength, count} = this.defaults;
const rectLength = parseInt(axleLength / count, 10);
const rect = new Path2D();
for (let i = 0; i <= count; i += 1) {
rect.rect(
point[0] + (rectLength * i),
point[1],
rectLength,
-rectLength * i
);
}
this.context.fill(rect);
}
draw() {
this.createAxle('x');
this.createAxle('y');
this.createScale('x');
this.createScale('y');
this.createRect();
}
}
const lineChart = new LineChart();
lineChart.draw();
複製代碼
結果以下所示:
剩下的工做還有一些,以後在更新吧!
PS:你們看了後以爲對本身有幫助能夠三連留言,歡迎提出寶貴意見,也歡迎各位對相關技術有興趣的開發者(由團隊開發人員微信號x118422邀請)入羣,在線解答討論數據可視化、優化圖表性能等方面的技術問題~