<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<canvas width="300" height="200" id="xx" style="border: 1px solid #ccc"></canvas>
<script>
class PieChart {
constructor(obj) {
console.log(obj.id,'===>obj',document.getElementById(obj.id))
// 获取画布
this.ctx = document.getElementById(obj.id)?.getContext("2d");
//获取画布的中心
this.x0 = this.ctx.canvas.width / 2;
this.y0 = this.ctx.canvas.height / 2;
//外圆半径
this.radius = this.x0 > this.y0 ? 0.5 * this.y0 : 0.5 * this.x0;
//内圆半径
this.inr=0.8*this.radius;
//标题伸出去的距离
this.outLine = 20;
// 字体大小
this.font=12;
// pie数据
this.pieData = obj.pieData || [];
// 动画定时器
this.timer=null;
// 速率
this.speed=0.1;
// 时间
this.rate=100;
// 圆点半径
this.circle=4;
}
//添加饼图
drawPie() {
//1、将数据转为弧度
var angleList = this.drawAngle();
let speed = this.speed;
this.timer = setInterval(() => {
if (speed >= 1) {
clearInterval(this.timer)
return
}
let aniAngleList= JSON.parse(JSON.stringify(angleList)).map((item) => {
item.angle = item.angle * speed
return item
})
var start = 0;//起始弧度
aniAngleList.forEach(function (item, i) {
var end = item.angle + start;
this.ctx.beginPath();
this.ctx.moveTo(this.x0, this.y0);
this.ctx.fillStyle = item.color;
this.ctx.arc(this.x0, this.y0, this.radius, start, end);
this.ctx.fill()
if (speed >= 0.9) {
//调用标的方法
this.drawTitle(start, item, this.ctx.fillStyle);
}
this.ctx.beginPath();
this.ctx.moveTo(this.x0, this.y0);
this.ctx.fillStyle = '#fff';
this.ctx.arc(this.x0, this.y0, this.inr, 0, Math.PI * 2);
this.ctx.fill()
//记录上一个结束的弧度
start = end;
}.bind(this));
speed += 0.1
}, this.rate)
}
//添加转化弧度的方法
drawAngle() {
//先获取数据的总和
var total = 0;
this.pieData.forEach((item, index)=> {
total += item.num;
});
//获取每条数据的弧度
this.pieData.forEach(function (item, index) {
var angle = item.num / total * Math.PI * 2;
item.angle = angle;
});
return this.pieData;
}
//添加标题
drawTitle(start, item, color) {
this.ctx.beginPath();
//斜边的长度
var edge = this.radius + this.outLine;
// 起点坐标
//x轴方向的直角边
var edgeX0 = this.radius * Math.cos(start + item.angle / 2);
//y轴方向的直角边
var edgeY0 = this.radius * Math.sin(start + item.angle / 2);
//x轴方向的直角边
var edgeX = edge * Math.cos(start + item.angle / 2);
//y轴方向的直角边
var edgeY = edge * Math.sin(start + item.angle / 2);
//伸出去的横纵坐标
var outX = this.x0 + edgeX;
var outY = this.y0 + edgeY;
this.ctx.beginPath();
// this.ctx.moveTo(this.x0 * 1.2, this.y0 * 1.2);
this.ctx.moveTo(this.x0 + edgeX0, this.y0 + edgeY0);
this.ctx.lineTo(outX, outY);
// this.ctx.strokeStyle = color;
this.ctx.strokeStyle = '#ccc';
this.ctx.stroke();
//添加字体
var align = outX > this.x0 ? "left" : "right";
this.ctx.font = this.font+"px 微软雅黑";
this.ctx.textAlign = align;
this.ctx.textBaseline = "bottom";
// this.ctx.fillStyle = color;
this.ctx.fillStyle = '#ccc';
let outX1 = outX > this.x0 ? outX + 1.5*this.font : outX - 1.5*this.font;
this.ctx.fillText(item.title, outX1, outY);
this.ctx.fillText(item.title, outX1, outY - this.font);
this.ctx.beginPath();
// 字前面的圆点
let dir = this.ctx.measureText(item.title).width
let outX2 = outX > this.x0 ? outX + 1.5*this.font - (this.font/2).toFixed(1) : outX - 1.5*this.font - (this.font/2).toFixed(1) - dir;
this.ctx.arc(outX2, outY - this.font/2-this.circle/4, this.circle, 0, 2 * Math.PI);
this.ctx.fillStyle = color;
this.ctx.fill();
// this.ctx.restore(); // 还原状态
//添加文字下面的线
var textW = this.ctx.measureText(item.title).width + this.font*2;
this.ctx.moveTo(outX, outY);
outX = outX > this.x0 ? outX + textW : outX - textW;
this.ctx.lineTo(outX, outY);
this.ctx.stroke();
}
}
let pieChart = new PieChart({
id:'xx',
pieData: [
{ title: "20岁以下", num: 1,color:'#306ABD' },
{ title: "20-25岁", num: 5,color:'#8272EE' },
{ title: "25-30岁", num: 4,color:'#306ABD' },
{ title: "30岁以上", num: 5 ,color:'#ED8661'},
{ title: "30岁以上", num: 5 ,color:'#F9D852'},
]
})
pieChart.drawPie()
</script>
<!-- Code injected by live-server -->
<script>
// <![CDATA[ <-- For SVG support
if ('WebSocket' in window) {
(function () {
function refreshCSS() {
var sheets = [].slice.call(document.getElementsByTagName("link"));
var head = document.getElementsByTagName("head")[0];
for (var i = 0; i < sheets.length; ++i) {
var elem = sheets[i];
var parent = elem.parentElement || head;
parent.removeChild(elem);
var rel = elem.rel;
if (elem.href && typeof rel != "string" || rel.length == 0 || rel.toLowerCase() == "stylesheet") {
var url = elem.href.replace(/(&|\?)_cacheOverride=\d+/, '');
elem.href = url + (url.indexOf('?') >= 0 ? '&' : '?') + '_cacheOverride=' + (new Date().valueOf());
}
parent.appendChild(elem);
}
}
var protocol = window.location.protocol === 'http:' ? 'ws://' : 'wss://';
var address = protocol + window.location.host + window.location.pathname + '/ws';
var socket = new WebSocket(address);
socket.onmessage = function (msg) {
if (msg.data == 'reload') window.location.reload();
else if (msg.data == 'refreshcss') refreshCSS();
};
if (sessionStorage && !sessionStorage.getItem('IsThisFirstTime_Log_From_LiveServer')) {
console.log('Live reload enabled.');
sessionStorage.setItem('IsThisFirstTime_Log_From_LiveServer', true);
}
})();
}
else {
console.error('Upgrade your browser. This Browser is NOT supported WebSocket for Live-Reloading.');
}
// ]]>
</script>
</body>
</html>
canvas画环形 pie
最新推荐文章于 2024-08-15 07:19:20 发布