Canvas(3)---繪製餅狀圖
有關canvas之前有寫過兩篇文章
在繪製餅狀圖之前,我們先要理解什麼是圓弧,如何在畫布中繪製文字等等。所以這裡將繪製餅狀圖理解拆分成以下幾個步驟:
1、理解圓弧
2、繪製一段圓弧
3、繪製一個扇形
4、繪製一個六等圓
5、繪製一個根據資料的餅圖
6、繪製在畫布中心的一段文字
7、繪製完整餅狀圖
什麼是弧度
弧度是一種長度的描述單位, 一個半徑的長度就表示一弧度,所以一個圓有2*π個弧度。
一、繪製一段圓弧
效果
程式碼
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
canvas {
border: 1px solid #00CED1;
}
</style>
</head>
<body>
<canvas width="600" height="400"></canvas>
<script>
var myCanvas = document.querySelector('canvas');
var ctx = myCanvas.getContext('2d');
/*引數*/
/*座標 x y 確定圓心 */
/*確定圓半徑 r */
/*確定起始繪製的位置和結束繪製的位置 Math.PI=π 也就是180度*/
/*取得繪製的方向 direction 預設是順時針 false 逆時針 true */
var w = ctx.canvas.width;
var h = ctx.canvas.height;
ctx.arc(w/2,h/2,150,Math.PI/2,Math.PI,false);
ctx.stroke();
</script>
</body>
</html>
思考
為什麼這裡四分之一的弧度是這個方向的,那是因為canvas指定了規則
所以上面 Math.PI/2 到 Math.PI,且是 順時針 的。由這兩點最終繪製的就是上面的效果了。
二、繪製一個扇形
效果
程式碼
<!-- 上面部分程式碼和上面一致,這裡就不重複寫了 -->
<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>
三、繪製一個圓分成六等分顏色隨機
效果
程式碼
<!-- 上面部分程式碼和上面一致,這裡就不重複寫了 -->
<script>
var myCanvas = document.querySelector('canvas');
var ctx = myCanvas.getContext('2d');
var w = ctx.canvas.width;
var h = ctx.canvas.height;
/*分成幾等分*/
var num = 6;
/*一份多少弧度*/
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 + ')';
}
/*上一次繪製的結束弧度等於當前次的起始弧度*/
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>
四、繪製一個根據資料的餅圖
上面是平均分成了6等分,這裡是根據具體的資料來按比例分成若干份。
效果
程式碼
<!-- 上面部分程式碼和上面一致,這裡就不重複寫了 -->
<script>
var myCanvas = document.querySelector('canvas');
var ctx = myCanvas.getContext('2d');
//資料
var data = [5, 10, 15, 20];
/*1.需要把資料轉出弧度 先計算總數*/
var total = 0;
data.forEach(function (item, i) {
total += item;
});
//2、計算每個資料所佔的弧度
var angleList = [];
data.forEach(function (item, i) {
var angle = Math.PI * 2 * (item/total);
angleList.push(angle);
});
/* 3、獲取隨機顏色*/
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 + ')';
}
/*4.根據弧度繪製扇形*/
var w = ctx.canvas.width;
var h = ctx.canvas.height;
var x0 = w/2;
var y0 = h/2;
var startAngle = 0;
angleList.forEach(function (item,i) {
/*上一次繪製的結束弧度等於當前次的起始弧度*/
var endAngle = startAngle + item;
ctx.beginPath();
ctx.moveTo(x0,y0);
ctx.arc(x0,y0,150,startAngle,endAngle);
ctx.fillStyle = getRandomColor();
ctx.fill();
/*記錄當前的結束位置作為下一次的起始位置*/
startAngle = endAngle;
});
</script>
五、繪製在畫布中心的一段文字
效果
程式碼
<html lang="en">
<head>
<meta charset="UTF-8">
<style>
canvas {
border: 1px solid #00CED1;
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);
ctx.lineTo(w, h / 2);
ctx.moveTo(w / 2, 0);
ctx.lineTo(w / 2, 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 #00CED1;
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);
ctx.lineTo(w, h / 2);
ctx.moveTo(w / 2, 0);
ctx.lineTo(w / 2, 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>
別人罵我胖,我會生氣,因為我心裡承認了我胖。別人說我矮,我就會覺得好笑,因為我心裡知道我不可能矮。這就是我們為什麼會對別人的攻擊生氣。
攻我盾者,乃我內心之矛(11)