构造函数绘制canvas饼状图

103 篇文章 0 订阅
97 篇文章 0 订阅
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>构造函数canvas饼状图</title>
    <style>
        canvas{
            border: 1px solid #ccc;
            display: block;
            margin: 50px auto;
        }
    </style>
</head>
<body>
    <canvas width="600" height="600"></canvas>

    <script>

        // 构造函数
        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;
            this.y0 = this.h / 2;

            // 半径
            this.radius = 150;

            // 文本伸出去的线
            this.outline = 40;

            // 说明矩形的大小
            this.rectw = 30;
            this.recth = 16;
            this.space = 20;
        }
        // 入口函数
        pieChart.prototype.init = function (data) { //提取数据
            this.drawpie(data);
        };

        // 行为函数
        pieChart.prototype.drawpie= function (data) {//获取数据 画圆

            var that = this;
            // 1,初始化数据
            var anglelist = this.transformAngle(data);

            // 2,绘制饼图

            // 生命记录上一个的结束位置||起始位置
            var startAngle = 0;
            anglelist.forEach(function(item,i){
                // 结束位置
                var endAngle = startAngle + item.angle;
                that.ctx.beginPath();
                that.ctx.moveTo(that.x0,that.y0);
                that.ctx.arc(that.x0,that.y0,that.radius,startAngle,endAngle);
                var color = that.ctx.fillStyle = that.getRandoColor();
                that.ctx.fill();

                // 调用绘制文本行为函数
                that.drawTitle(startAngle,item.angle,color,item.title);
                
                // 绘制说明
                that.drawDesc(i,item.title);
                
                // 获取当前的结束角度
                startAngle = endAngle;
            });


        };

        pieChart.prototype.drawTitle= function (startAngle,angle,color,title) {//文本

            // c点
            var edge = this.radius + this.outline;
            // x轴方向的直角边
            var edgex = Math.cos(startAngle + angle / 2) * edge;
            // 轴方向的直角边
            var edgey = Math.sin(startAngle + angle / 2) * edge;
            // 计算出去的点坐标
            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.strokeStyle = color;
            this.ctx.stroke();

        // 伸出去的

            // 判断伸出去的点在xod的左边 线的方向就是左边
            // 判断伸出去的点在xod的右边 线的方向就是右边

            this.ctx.font = '14px Fira Code';

            var textwidth = this.ctx.measureText(title).width;

            // 判断伸出去的方向
            if(outx > this.x0 ){
                // 左
                this.ctx.lineTo(outx + textwidth,outy);
                this.ctx.textAlign = 'left';
            }else{
                // 右
                this.ctx.lineTo(outx - textwidth,outy);
                this.ctx.textAlign = 'right';
            }

            this.ctx.stroke();
            this.ctx.textBaseline = 'bottom';

            this.ctx.fillText(title,outx,outy);
        };

        pieChart.prototype.drawDesc = function (index,title) { //说明矩形描述
            this.ctx.fillRect(this.space,this.space + index * (this.recth + 10),this.rectw,this.recth)

            this.ctx.beginPath();
            this.ctx.textAlign = 'left';
            this.ctx.textBaseline = 'top';
            this.ctx.font = '14px Fira Code';
            // 绘制文字
            this.ctx.fillText(title,this.space + this.rectw + 10,this.space + index * (this.recth + 10))
        
        };

        //计算弧度
        pieChart.prototype.transformAngle = function (data) { 
            // 获取数组的numd的数据
            var total = 0;
            data.forEach(function (item,i) {
                 total += item.num; 
            });

            // 计算每一个数据的弧度
            data.forEach(function (item,i) {
                var angle = item.num / total * Math.PI * 2;

                // 把弧度追加到data中
                item.angle = angle;
            });
            return data;
        };

        //随机颜色
        pieChart.prototype.getRandoColor = function () { 
            var r = Math.floor(Math.random()*256);
            var g = Math.floor(Math.random()*256);
            var b = Math.floor(Math.random()*256);
            return 'rgb('+r+','+g+','+b+')';
        };

        // 数据
        var data = [
            {
                title:'15-20岁',
                num:6
            },{
                title:'20-25岁',
                num:30
            },{
                title:'25-30岁',
                num:10
            },{
                title:'30以上',
                num:8
            }
        ];

        // 初始化数据
        var pieChart = new pieChart();
        pieChart.init(data);
    </script>
</body>
</html>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值