1.函數說明
封裝一個根據數據來繪制帶說明的餅圖的函數(插件),具體的功能包括:
隨機顏色獲取
各區間角度值的計算
扇形繪制(包括延長線及說明)
左上角顏色說明
畫布建議大小為700 * 400
傳入的數據格式為:
var data = [
{num:"10",title:"16-22的年齡人數"},
{num:"15",title:"23-30的年齡人數"},
{num:"25",title:"31-35的年齡人數"},
{num:"10",title:"36及以上的年齡人數"}
]
2.調用函數繪制餅圖
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Test</title>
<script src="index.js"></script>
<style>
.box{
width: 700px;
height: 400px;
margin: 20px auto;
}
.box > canvas{
border:1px solid red;
}
</style>
</head>
<body>
<div class="box">
<canvas width="700" height="400"></canvas>
</div>
</body>
<script>
var canvas = document.querySelector("canvas")
var ctx = canvas.getContext("2d")
var data = [
{num:0,title:"16-22的年齡人數"},
{num:0,title:"23-30的年齡人數"},
{num:0,title:"31-35的年齡人數"},
{num:0,title:"36及以上的年齡人數"}
]
//模擬數據(產生50個數據)
var num = 50
for(var i=0;i<num;i++){
//隨機產生16-40的整數
var age = Math.floor(16 + Math.random()*25)
if(age < 23){
data[0].num++
}else if(age < 31){
data[1].num++
}else if(age < 36){
data[2].num++
}else{
data[3].num++
}
}
//創建餅圖對象
var pieChart = new PieChart(ctx)
//傳入數據開始繪制餅圖
pieChart.init(data)
</script>
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 + 50;
this.y0 = this.h / 2;
this.r = 150; //半徑
//延長線的長度
this.outLineWidth = this.r + 20;
//說明矩形的大小
this.rectW = 30;
this.rectH = 16;
this.space = 20;
}
PieChart.prototype.init = function(data) {
this.drawPie(data);
}
PieChart.prototype.drawPie = function(data) {
var angleList = this.transitionRadian(data);
var startRadian = 0; //起始角度
var rectY = this.space; //說明矩形的起始Y坐標
for (var i = 0; i < angleList.length; i++) {
//繪制扇形
this.ctx.beginPath(); //開啟路徑
//獲取隨機顏色
var color = this.getRandomColor();
this.ctx.fillStyle = color; //設置填充顏色
//結束弧度 = 上一個區間的弧度 + 此區間所占的弧度
var endRadian = startRadian + angleList[i].angle;
this.ctx.arc(this.x0, this.y0, this.r, startRadian, endRadian);
this.ctx.lineTo(this.x0, this.y0);
this.ctx.fill();
//繪制餅圖的延長線標題
this.drawTitle(startRadian, endRadian, angleList[i].title, color);
//繪制左上角顏色說明
this.drawDesc(rectY, color, angleList[i].title);
//更新prevDadian
startRadian = endRadian;
//更新矩形的起始Y坐標
rectY += (this.rectH + 10);
}
}
PieChart.prototype.drawTitle = function(startRadian, endRadian, title, color) {
//計算中心角度
var middleRadian = (startRadian + endRadian) / 2;
//以outLineWidth為直角邊
//根據正弦 余弦求出兩個邊的長度,再結合圓心的坐標,求出延長線兩點的坐標
var outX = this.x0 + this.outLineWidth * Math.cos(middleRadian);
var outY = this.y0 + this.outLineWidth * Math.sin(middleRadian);
//設置字體(設置字體要在計算字體寬度之前)
this.ctx.font = '12px 微軟雅黑';
//設置文字基線
this.ctx.textBaseline = 'bottom';
//設置描邊顏色
this.ctx.strokeStyle = color;
//計算下划線的終點坐標及文字對齊方式
if (outX >= this.x0) {
//在右邊
var underlineX = outX + this.ctx.measureText(title).width;
this.ctx.textAlign = 'left';
} else {
//在左邊
var underlineX = outX - this.ctx.measureText(title).width;
this.ctx.textAlign = 'right';
}
//繪制延長線
this.ctx.beginPath();
this.ctx.moveTo(this.x0, this.y0);
this.ctx.lineTo(outX, outY);
this.ctx.lineTo(underlineX, outY);
this.ctx.stroke();
//繪制文本
this.ctx.beginPath();
this.ctx.fillText(title, outX, outY);
}
//繪制左上角的說明
PieChart.prototype.drawDesc = function(rectY, color, title) {
this.ctx.beginPath();
this.ctx.textAlign = 'left';
//中線對齊
this.ctx.textBaseline = 'middle';
//繪制矩形
this.ctx.fillRect(this.space, rectY, this.rectW, this.rectH);
//繪制文字,文字的基點y坐標為矩形的垂直方向的中心
this.ctx.fillText(title, this.space + this.rectW + 10, rectY + this.rectH / 2);
}
//為每個區間添加角度屬性
PieChart.prototype.transitionRadian = function(data) {
//獲取統計的總人數
var total = 0;
for (var i = 0; i < data.length; i++) {
total += data[i].num;
}
for (var i = 0; i < data.length; i++) {
var angle = 2 * Math.PI * Number(data[i].num) / total;
data[i].angle = angle;
}
return data;
}
//獲取隨機顏色
PieChart.prototype.getRandomColor = function() {
var r = Math.round(Math.random() * 255);
var g = Math.round(Math.random() * 255);
var b = Math.round(Math.random() * 255);
return 'rgb(' + r + ',' + g + ',' + b + ')';
}