zoukankan      html  css  js  c++  java
  • Canvas(3)---绘制饼状图

    Canvas(3)---绘制饼状图

    有关canvas之前有写过两篇文章

    1、Canvas(1)---概述+简单示例

    2、Canvas(2)---绘制折线图

    在绘制饼状图之前,我们先要理解什么是圆弧,如何在画布中绘制文字等等。所以这里将绘制饼状图理解拆分成以下几个步骤:

    1、理解圆弧
    2、绘制一段圆弧
    3、绘制一个扇形
    4、绘制一个六等圆
    5、绘制一个根据数据的饼图
    6、绘制在画布中心的一段文字
    7、绘制完整饼状图
    

    什么是弧度 弧度是一种长度的描述单位, 一个半径的长度就表示一弧度,所以一个圆有2*π个弧度。

    一、绘制一段圆弧

    效果

    代码

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <style>
            canvas {
                border: 1px solid #00CED1;
            }
        </style>
    </head>
    <body>
    <canvas width="600" height="400"></canvas>
    <script>
        var myCanvas = document.querySelector('canvas');
        var ctx = myCanvas.getContext('2d');
        /*参数*/
        /*坐标 x y 确定圆心  */
        /*确定圆半径  r */
        /*确定起始绘制的位置和结束绘制的位置 Math.PI=π 也就是180度*/
        /*取得绘制的方向 direction 默认是顺时针 false 逆时针 true */
        var w = ctx.canvas.width;
        var h = ctx.canvas.height;
        ctx.arc(w/2,h/2,150,Math.PI/2,Math.PI,false);
        ctx.stroke();
    </script>
    </body>
    </html>
    

    思考 为什么这里四分之一的弧度是这个方向的,那是因为canvas指定了规则

    所以上面 Math.PI/2Math.PI,且是 顺时针 的。由这两点最终绘制的就是上面的效果了。


    二、绘制一个扇形

    效果

    代码

    <!-- 上面部分代码和上面一致,这里就不重复写了 -->
    <script>
        var myCanvas = document.querySelector('canvas');
        var ctx = myCanvas.getContext('2d');
        /*在中心位置画一个半径150px的圆弧右上角 扇形  边  填充 */
        var w = ctx.canvas.width;
        var h = ctx.canvas.height;
        /*把起点放到圆心位置*/
        ctx.moveTo(w/2,h/2);
        ctx.arc(w/2,h/2,150,0,-Math.PI/2,true);
        //注意这里采用的是填充 ,而不是闭合 ctx.closePath()
        ctx.fill();
    </script>
    

    三、绘制一个圆分成六等分颜色随机

    效果

    代码

    <!-- 上面部分代码和上面一致,这里就不重复写了 -->
    <script>
        var myCanvas = document.querySelector('canvas');
        var ctx = myCanvas.getContext('2d');
    
        var w = ctx.canvas.width;
        var h = ctx.canvas.height;
    
        /*分成几等分*/
        var num = 6;
        /*一份多少弧度*/
        var angle = Math.PI * 2 / num;
        /*原点坐标*/
        var x0 = w / 2;
        var y0 = h / 2;
    
        /*获取随机颜色*/
        var getRandomColor = 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 + ')';
        }
        /*上一次绘制的结束弧度等于当前次的起始弧度*/
        for (var i = 0; i < num; i++) {
            var startAngle = i * angle;
            var endAngle = (i + 1) * angle;
            ctx.beginPath();
            ctx.moveTo(x0, y0);
            ctx.arc(x0, y0, 150, startAngle, endAngle);
            /*随机颜色*/
            ctx.fillStyle = getRandomColor();
            ctx.fill();
        }
    </script>
    

    四、绘制一个根据数据的饼图

    上面是平均分成了6等分,这里是根据具体的数据来按比例分成若干份。

    效果

    代码

    <!-- 上面部分代码和上面一致,这里就不重复写了 -->
    <script>
        var myCanvas = document.querySelector('canvas');
        var ctx = myCanvas.getContext('2d');
    
        //数据
        var data = [5, 10, 15, 20];
        /*1.需要把数据转出弧度 先计算总数*/
        var total = 0;
        data.forEach(function (item, i) {
            total += item;
        });
        //2、计算每个数据所占的弧度
        var angleList = [];
        data.forEach(function (item, i) {
            var angle = Math.PI * 2 * (item/total);
            angleList.push(angle);
        });
       /* 3、获取随机颜色*/
        var getRandomColor = 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 + ')';
        }
        /*4.根据弧度绘制扇形*/
        var w = ctx.canvas.width;
        var h = ctx.canvas.height;
        var x0 = w/2;
        var y0 = h/2;
        var startAngle = 0;
        angleList.forEach(function (item,i) {
            /*上一次绘制的结束弧度等于当前次的起始弧度*/
            var endAngle = startAngle + item;
            ctx.beginPath();
            ctx.moveTo(x0,y0);
            ctx.arc(x0,y0,150,startAngle,endAngle);
            ctx.fillStyle = getRandomColor();
            ctx.fill();
            /*记录当前的结束位置作为下一次的起始位置*/
            startAngle = endAngle;
        });
    </script>
    

    五、绘制在画布中心的一段文字

    效果

    代码

    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <style>
            canvas {
                border: 1px solid #00CED1;
                display: block;
                margin: 100px auto;
            }
        </style>
    </head>
    <body>
    <canvas width="600" height="400"></canvas>
    <script>
        var myCanvas = document.querySelector('canvas');
        var ctx = myCanvas.getContext('2d');
        /*1.在画布的中心绘制一段文字*/
        /*2.申明一段文字*/
        var str = '武汉加油';
        /*3.确定画布的中心*/
        var w = ctx.canvas.width;
        var h = ctx.canvas.height;
        /*4.画一个十字架在画布的中心*/
        ctx.beginPath();
        ctx.moveTo(0, h / 2);
        ctx.lineTo(w, h / 2);
        ctx.moveTo(w / 2, 0);
        ctx.lineTo(w / 2, h);
        ctx.strokeStyle = '#eee';
        ctx.stroke();
        /*5.绘制文本*/
        ctx.beginPath();
        ctx.strokeStyle = '#000';
        var x0 = w/2;
        var y0 = h/2;
        /*注意:起点位置在文字的左下角*/
        /*有文本的属性  尺寸 字体  左右对齐方式  垂直对齐的方式*/
        ctx.font = '40px Microsoft YaHei';
        /*左右对齐方式 (center left right start end) 基准起始坐标*/
        ctx.textAlign = 'center';
        /*垂直对齐的方式 基线 baseline(top,bottom,middle) 基准起始坐标*/
        ctx.textBaseline = 'middle';
        //ctx.direction = 'rtl';
        //ctx.strokeText(str,x0,y0);
        ctx.fillText(str,x0,y0);
        /*6.画一个下划线和文字一样长*/
        ctx.beginPath();
        /*获取文本的宽度*/
        console.log(ctx.measureText(str));
        var width = ctx.measureText(str).width;
        ctx.moveTo(x0-width/2,y0 + 20);
        ctx.lineTo(x0+width/2,y0 + 20);
        ctx.stroke();
    </script>
    </body>
    </html>
    

    六、绘制完整饼状图

    上面所做的都是为了整个饼状图做铺垫的。

    效果

    代码

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <style>
            canvas {
                border: 1px solid #00CED1;
                display: block;
                margin: 100px auto;
            }
        </style>
    </head>
    <body>
    <canvas width="600" height="400"></canvas>
    <script>
        var myCanvas = document.querySelector('canvas');
        var ctx = myCanvas.getContext('2d');
    
        /*1.在画布的中心绘制一段文字*/
        /*2.申明一段文字*/
        var str = '武汉加油';
        /*3.确定画布的中心*/
        var w = ctx.canvas.width;
        var h = ctx.canvas.height;
        /*4.画一个十字架在画布的中心*/
        ctx.beginPath();
        ctx.moveTo(0, h / 2);
        ctx.lineTo(w, h / 2);
        ctx.moveTo(w / 2, 0);
        ctx.lineTo(w / 2, h);
        ctx.strokeStyle = '#eee';
        ctx.stroke();
        /*5.绘制文本*/
        ctx.beginPath();
        ctx.strokeStyle = '#000';
        var x0 = w/2;
        var y0 = h/2;
        /*注意:起点位置在文字的左下角*/
        /*有文本的属性  尺寸 字体  左右对齐方式  垂直对齐的方式*/
        ctx.font = '40px Microsoft YaHei';
        /*左右对齐方式 (center left right start end) 基准起始坐标*/
        ctx.textAlign = 'center';
        /*垂直对齐的方式 基线 baseline(top,bottom,middle) 基准起始坐标*/
        ctx.textBaseline = 'middle';
        //ctx.direction = 'rtl';
        //ctx.strokeText(str,x0,y0);
        ctx.fillText(str,x0,y0);
        /*6.画一个下划线和文字一样长*/
        ctx.beginPath();
        /*获取文本的宽度*/
        console.log(ctx.measureText(str));
        var width = ctx.measureText(str).width;
        ctx.moveTo(x0-width/2,y0 + 20);
        ctx.lineTo(x0+width/2,y0 + 20);
        ctx.stroke();
    </script>
    </body>
    </html>
    


    别人骂我胖,我会生气,因为我心里承认了我胖。别人说我矮,我就会觉得好笑,因为我心里知道我不可能矮。这就是我们为什么会对别人的攻击生气。
    攻我盾者,乃我内心之矛(11)
    
  • 相关阅读:
    netty的基本使用
    netty 实现简单的rpc调用
    NIO 的基本使用
    BIO实现 Socket 通信
    springboot使用ElasticSearch
    docker-compose安装rabbitmq集群(主从集群---》镜像集群)
    杂谈:面向微服务的体系结构评审中需要问的三个问题
    使用Spring Boot和RxJava的构建响应式REST API
    JVM体系结构详解
    如何成为更好的程序员?
  • 原文地址:https://www.cnblogs.com/qdhxhz/p/12405780.html
Copyright © 2011-2022 走看看