涉及到的知识
弧度:两条射线从圆心射出形成的一个夹角,夹角所正对的线段就叫弧度 当这个弧长等于圆的半径时,两条射线的夹角为1
一个角有多少弧度 2πr/r=2π 一个圆的角度是360°
一个角度等于多少弧度 2π/360=π/180
用到的方法
- arc(x,y,r,startAngle ,endAngle,anticlockwise )
- 参数
- x 圆心横坐标
- y 圆心纵坐标
- r 半径
- startAngle 开始角度
- endAngle 结束角度
- anticlockwise 是否逆时针方向绘制(默认false表示顺时针;true表示逆时针)
开始绘制饼状图
定义一个按方法
function PieVhart() {
this.ctx = document.querySelector("canvas").getContext("2d");
//获取画布的中心
this.X0 = this.ctx.canvas.width / 2 + 60;
this.Y0 = this.ctx.canvas.height / 2;
// 获取半径
this.radius = 150;
// 自定义伸出去的小线段
this.outline = 20;
// 定义左上角说明的矩形
//x坐标
this.declarationX = 20;
// y坐标
this.declarationY = 10;
//宽度
this.declarationW = 25;
//高度
this.declarationH = 15;
}
初始化饼状图
PieVhart.prototype.init = function () {
this.drawPie();
}
//添加饼图
PieVhart.prototype.drawPie = function () {
//1.转化为弧度
var angelList = this.drawAngel();
var start = 0;//记录开始弧度
angelList.forEach(function (item, i) {
var end = start + item.angle;
this.ctx.beginPath();
this.ctx.moveTo(this.X0, this.Y0);
this.ctx.arc(this.X0, this.Y0, this.radius, start, end);
//设置扇形的随机颜色
var colors = this.ctx.fillStyle = this.randomColor();
this.ctx.fill();
//调用标题的方法
this.drawTitle(start, item.angle, colors, item.title);
this.drawText(item.title, i);
start = end;
}.bind(this))
}
//添加标题
PieVhart.prototype.drawTitle = function (start, angel, colors, title) {
//1.确定伸出去的线=半径+伸出去的小线段(自定义)
//2.确定对边 即Y轴方向的长度=斜边*sin(角度)
//3.邻边 即x方向的长度=斜边*cos(角度)
//4.伸出去的点的横纵坐标
// outX=x0+(radius+outLine)*cos(角度)
// outY=y0+(radius+outLine)*sin(角度)
//5.角度在canvas用弧度=当前扇形的起始弧度+对应弧度的一半
//斜边的长度
var edge = this.radius + this.outline;
//x轴方向的直角边
var edgeX = edge * Math.cos(start + angel / 2);
//y轴方向的直角边
var edgeY = edge * Math.sin(start + angel / 2);
//伸出去的横坐标
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.font = "14px 微软雅黑";
var textW = this.ctx.measureText(title).width;
this.ctx.textBaseline = "bottom"
//判断
if (outX > this.X0) {
this.ctx.fillText(title, outX, outY);
this.ctx.moveTo(outX, outY);
this.ctx.lineTo(outX + textW, outY);
}
if (outX < this.X0) {
this.ctx.fillText(title, outX - textW, outY);
this.ctx.moveTo(outX, outY);
this.ctx.lineTo(outX - textW, outY);
}
this.ctx.strokeStyle = colors;
this.ctx.stroke();
}
//添加说明
PieVhart.prototype.drawText = function (title, i) {
i *= 2
this.ctx.fillRect(this.declarationX, this.declarationY * i + this.declarationY, this.declarationW, this.declarationH);
console.log(this.declarationY * i + this.declarationY);
this.ctx.font = "14px 幼圆"
this.ctx.textBaseline = "bottom"
this.ctx.fillText(title, this.declarationX + this.declarationW + 10, this.declarationY * i + this.declarationY+15);
console.log( this.declarationY * i + this.declarationY)
}
模拟数据
var data = [
{title: "20岁以下", num: 6},
{title: "20-25岁", num: 30},
{title: "25-30岁", num: 20},
{title: "30岁以上", num: 4},
]
转化为弧度的方法
PieVhart.prototype.drawAngel = function () {
//获取数据的总和
var total = 0;
data.forEach(function (item, i) {
total += item.num;
})
//获取每条数据的弧度
data.forEach(function (item, i) {
var angel = item.num / total * 2 * Math.PI;
item.angle = angel;
})
return data;
};
封装转化为弧度的函数
PieVhart.prototype.drawAngel = function () {
//获取数据的总和
var total = 0;
data.forEach(function (item, i) {
total += item.num;
})
//获取每条数据的弧度
data.forEach(function (item, i) {
var angel = item.num / total * 2 * Math.PI;
item.angle = angel;
})
return data;
};
封装产生随机颜色的函数
PieVhart.prototype.randomColor = function () {
var r = Math.floor(Math.random() * 250);
var g = Math.floor(Math.random() * 250);
var b = Math.floor(Math.random() * 250);
return 'rgb(' + r + ',' + g + ',' + b + ')'
}
调用原型里面方法
var pieVhart = new PieVhart();
pieVhart.init();
最终效果图 每次刷新相对应的都数据都可以相应的改变颜色