Canvas根据数据绘制饼形统计图

我们只要不是要去用 canvas 做游戏,那只要能做到 让 数据 可视图形化 即可,下面是 canvas 绘制饼形统计图的练习

<canvas width="600" height="400" id="cas" style='border: 1px solid black;'></canvas>
<script>
    /* 公共方法 */
    // 弧度与角度的互相切换
    function toAngle( radian ) { return radian * 180 / Math.PI }
    function toRadian( angle ) { return angle * Math.PI / 180 }

    var cas = document.getElementById( 'cas' );
    var ctx = cas.getContext( '2d' );   // 获取绘图对象

    // 根据数据绘制饼形图,准备一组数据
    var data = [ 123, 234, 78, 356, 449 ];
    // 准备一组颜色数据
    var colors = "red,hotpink,indianred,indigo,blue,lavender,lavenderblush,lawngreen,lemonchiffon".split( ',' );
    // 求和以计算占比
    var sum = 0;
    data.forEach( function( v ) { sum += v; } );
    // 根据总和,计算每一个百分比和角度 { value: 123, angle: 角度, text:文字描述 }
    var data2 = data.map( function( v ) {
        return {value : v, angle : v * 360 / sum, text : v + ",占比:" + (v / sum * 100).toFixed( 2 ) + '%'}
    } );
    console.log( data2 );

    /* 准备绘制 */
    var angle = -90, // 绘制起始角度
        x = cas.width / 2, // 圆心 x 坐标
        y = cas.height / 2, // 圆心 y 坐标
        r = 100; // 半径
    var x1, y1; // 记录描述文字的坐标
    var distance = 30; // 指示线超出圆饼的距离
    var txtLine; // 文本下划线
    var paddingX = 20 / 3, paddingY = 20 / 3; // 设置文本的移动

    /* 遍历数据进行绘制 */
    data2.forEach( function( v, i ) {
        // 绘制扇形
        ctx.beginPath(); // 开启路径  因为每次都要换颜色
        ctx.fillStyle = colors[ i ];    // 设置 fill 颜色
        ctx.moveTo( x, y ); // 画笔移动到 ( x, y )
        ctx.arc( x, y , r, toRadian( angle ), toRadian( angle + v.angle ) ); // 绘制圆弧
        ctx.fill(); // fill 路径补全,填充成扇形

        /*--- 绘制文本 ----*/
        // 绘制直线
        ctx.beginPath(); // 开启路径,因为要切换绘制方式
        ctx.strokeStyle = colors[ i ]; // 设置 stroke 颜色
        ctx.moveTo( x, y ); // 画笔移动到 ( x, y )
        x1 = x + (r + distance) * Math.cos( toRadian(angle + v.angle / 2) ); //文字 x 坐标
        y1 = y + (r + distance) * Math.sin( toRadian(angle + v.angle / 2) ); //文字 y 坐标
        ctx.lineTo( x1, y1 ); // 连线
        // 绘制横线
        txtLine = ctx.measureText( v.text ).width + 2 * Math.abs( paddingX );
        // 根据 是往左还是往右,设置 texLine 的 正负
        if ( angle + v.angle / 2 < 270 && angle + v.angle / 2 > 90 ) {
            txtLine = -ctx.measureText( v.text ).width - 2 * Math.abs(paddingX);
        }
        ctx.lineTo( x1 + txtLine, y1 );
        ctx.stroke(); // 绘制

        // 写文字
        if ( angle + v.angle / 2 < 270 && angle + v.angle / 2 > 90 ) {
            ctx.textAlign = 'right';
            paddingX = - 20 / 3;
        }
        ctx.fillText( v.text , x1 + paddingX, y1 - paddingY );

        angle += v.angle;   // 角度加上去
    });

</script>

最终绘制出来的效果:
这里写图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值