canvas利用绘制圆形的知识来绘制饼状图 - Kaiqisan

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
        }
    }

最终效果

chart

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kaiqisan

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值