canvas利用绘制圆形的知识来绘制饼状图
就是利用了前一课的知识
https://blog.csdn.net/qq_33933205/article/details/107185489
基本思路
根据实际数据来绘制不同角度的扇形,然后将这些扇形拼接成一个完整的圆,就变成了饼状图,然后再在各个扇形的角平分线处添加一条延伸出去的线标注成员。
需要注意的是,绘制弧形时的起始角是与平面直角坐标系是完全一致的,所以,所有的角度选择应以起始角为标准,这样可以简化运算过程。
参考源码
window.onload = function () {
let colorList = ['#9B59B6', '#52BE80', '#2E86C1', '#CB4335', '#F8C471', '#AAB7B8', '#283747', '#D68910', '#DC7633'] // 随机颜色列表
let expenditure = [ // 模型数据
{
name: '食品支出',
money: 5500
},
{
name: '服装支出',
money: 2000
},
{
name: '杂项食品支出',
money: 1000
},
{
name: '娱乐支出食品支出',
money: 500
},
{
name: '房租支出食品支出',
money: 1000
},
{
name: '教育支出',
money: 3000
}
]
let canvas = document.getElementById('demo')
let ctx = canvas.getContext('2d')
let allMoney = 0 // 累计所有钱
for (let index in expenditure) {
allMoney += expenditure[index].money
}
let hasDone = 0 // 统计已经统计的成员的总金额,用于绘制起始角。
// 画饼图
for (let i = 0; i < expenditure.length; i++) {
// 这里定义了第一个扇形起始角从12点钟方向开始并顺时针开始产生新的扇形图,最后拼接成完整的圆形
let startAngle = (-90 + hasDone / allMoney * 360) * Math.PI / 180
let endAngle = (-90 + (hasDone + expenditure[i].money) / allMoney * 360) * Math.PI / 180
ctx.beginPath()
ctx.moveTo(400, 300) // 选择圆心坐标,先移动画笔
ctx.arc(400, 300, 200, startAngle, endAngle, false)
ctx.lineWidth = 2
ctx.fillStyle = getColor() // 获取随机颜色
ctx.fill()
// ctx.strokeStyle = '#444444' // 看个人选择是否添加扇形的边缘线
// ctx.stroke()
// 画说明线
let angel = Math.PI * 2 - (startAngle + endAngle) / 2 // 找角平分线
let x, y
x = 400 + 250 * Math.cos(angel)
y = 300 - 250 * Math.sin(angel)
// 这里比较吃数学底力,前面四行代码如果你愿意再在图里再画一遍的话一定可以理解
ctx.beginPath()
ctx.moveTo(400, 300)
ctx.lineTo(x, y)
ctx.strokeStyle = '#444444'
ctx.stroke()
// 填充文字
ctx.beginPath()
// ctx.textBaseline = 'top' // 看图
ctx.font = '15px "幼圆"' // 设置字体(字体和尺寸)
if (angel >= Math.PI / 2 && angel <= 3 * Math.PI / 2) {
ctx.textAlign = 'end' // 对齐方式,当文字出现在饼图左边,文字就右对齐,反之就左对齐,这样可以防止文字和说明线重合导致不美观
} else {
ctx.textAlign = 'start'
}
ctx.fillText(expenditure[i].name, x, y)
hasDone += expenditure[i].money // 当前已统计数据开始累加
}
// 获取随机颜色
function getColor() {
let a = ~~(Math.random() * colorList.length)
let color = colorList[a]
colorList.splice(a, 1)
return color
}
}