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 + ')';
}