zoukankan      html  css  js  c++  java
  • canvas画扇形、饼图

    画扇形的方法

    方法一:起始角度是0,那么第一条线就是line(r,0),通过旋转扇形的角度,第二条线就是line(r,0)

    //圆弧
    ctx.save();
    ctx.translate(100, 100);
    ctx.arc(0,0,100,0, 30*Math.PI/180);
    ctx.restore();
    //第一条线
    ctx.save();
    ctx.moveTo(100,100);
    ctx.lineTo(200,100);
    ctx.restore();
    //第二条线
    ctx.save();
    ctx.translate(100, 100);
    ctx.moveTo(0,0);
    ctx.rotate(30*Math.PI/180);
    ctx.lineTo(100,0);
    ctx.stroke();
    ctx.restore();

    第一步为什么是设置原点呢,为什么不用moveTo来设置起始点呢?

      因为画布的默认原点在0,0的位置上,如果用moveTo来设置起始点,原点依然还在0,0的位置,而变换是以原点为基准点的,即使你设置了起始点,但是起始点不是原点的话,图形旋转依然会围绕0,0点旋转然后自转,得到的图形就不知道是什么图形了。

    方法二

    //将原点设置100,100位置
    ctx.translate(100,100);
    //原点在100,100,则圆心设为0,0 ——> 100,100的位置
    ctx.arc(0,0,100,30*Math.PI/180,60*Math.PI/180);
    //save(),restore()是为了防止角度旋转的污染
    ctx.save();
    ctx.rotate(30*Math.PI/180);
    ctx.moveTo(0,0);
    ctx.lineTo(100,0);
    ctx.restore();
    ctx.rotate(60*Math.PI/180);
    ctx.moveTo(0,0);
    ctx.lineTo(100,0);
    ctx.stroke();

    关于save()和restore():

      其作用不只是可以防止外面的属性或方法对里面的绘制产生影响,它的本质意思是save()保存当前环境的状态,restore()返回之前保存路径的状态。在这里要注意还原的触点在什么地方,如下例子:

     1 //将原点设置100,100位置
     2 ctx.translate(100,100);
     3 //原点在100,100,则圆心设为0,0 ——> 100,100的位置
     4 ctx.arc(0,0,100,30*Math.PI/180,60*Math.PI/180);
     5 //save(),restore()是为了防止角度旋转的污染
     6 ctx.save();
     7 ctx.rotate(30*Math.PI/180);
     8 ctx.moveTo(0,0);
     9 ctx.lineTo(100,0);
    10 ctx.restore();
    11 ctx.rotate(60*Math.PI/180);
    12 ctx.lineTo(100,0);
    13 ctx.stroke();

    跟上面的代码比就是少了12行的moveTo(0,0),结果如下图1:

    原因是:线在旋转的时候,是从它的起点为圆心旋转的,而上面的代码是,第一条线从圆心开始,到圆弧的起点(旋转过后),自然现在的起点就是圆弧的起点了,然后再rotate(60*Math.PI/180);lineTo(100,0);就是从圆弧的起点画到(100,0)的线了

    现在我们将第一条直线的起点设在(r,0)的位置,旋转后就到了圆弧的起始点,然后在画到圆心地方,那现在的起始点就是圆心了,再画一条线到圆弧,就可以了,如下:

    //将原点设置100,100位置
    ctx.translate(100,100);
    //原点在100,100,则圆心设为0,0 ——> 100,100的位置
    ctx.arc(0,0,100,30*Math.PI/180,60*Math.PI/180);
    //save(),restore()是为了防止角度旋转的污染
    ctx.save();
    ctx.rotate(30*Math.PI/180);
    ctx.moveTo(100,0);
    ctx.lineTo(0,0);
    ctx.restore();
    ctx.rotate(60*Math.PI/180);
    ctx.lineTo(100,0);
    ctx.stroke();

     方法三:充分使用触点的作用,当我们再画圆弧的时候,画完之后其触点在圆弧的结束位置,为何不直接将这个触点作为起点,画一条到圆心的线,然后再画第二条线。如下代码:

    //将原点设置100,100位置
    ctx.translate(100,100);
    //原点在100,100,则圆心设为0,0 ——> 100,100的位置
    ctx.arc(0,0,100,30*Math.PI/180,60*Math.PI/180);
    //以圆弧终点为起点画直线,rotate使得直角坐标系旋转了30°
    ctx.lineTo(0,0);
    ctx.rotate(30*Math.PI/180);
    //以0,0为起点画直线
    ctx.lineTo(100,0);
    ctx.stroke();

    方法四:配合beginPath()和closePath()

    为什么要用translate,而不要moveTo,是因为如果需要旋转,所以就需要原点,现在不需要旋转,而是正常的画图,那么就不需要原点,就可以用moveTo。

    配合beginPath()和closePath(),就会将一个圆弧封闭起来。

    ctx.beginPath();
    //定义起点
    ctx.moveTo(100,100);
    //以起点为圆心,画一个半径为100的圆弧
    ctx.arc(100,100,100,30*Math.PI/180, 60*Math.PI/180);
    ctx.closePath();
    ctx.stroke();

     特别注意:

    • 使用arc()绘制图形时,如果没有设置moveTo(),那么会从圆弧的开始的点作为起始点。如果设置了moveTo(),那么该点会连线到圆弧起始点。
    • 如果使用stroke()方法,那么会从开始连线到圆弧的起始位置。 如果是 fill 方法, 会自动闭合路径填充

    封装函数

    CanvasRenderingContext2D.prototype.sector = function(x,y,r,angle1,angle2){
                this.save();
                this.beginPath();
                this.moveTo(x,y);
                this.arc(x,y,r,angle1*Math.PI/180,angle2*Math.PI/180,false);
                this.closePath();    
                this.restore();
                return this;
            }
            ctx.fillStyle = 'red';
            ctx.sector(200,200,100,30,150).fill();
            ctx.fillStyle = 'green';
            ctx.sector(200,200,100,150,270).fill();
            ctx.fillStyle = 'blue';
            ctx.sector(200,200,100,270,390).fill(); 

    画饼图

    思路:

    1)将每块饼的占比以整数形式储存在数组nums中,将每个饼的颜色以字符串形式储存在数组colors中,两个数组的值一一对应。将画布旋转坐标定义在即将绘制圆的中心,定义绘制圆弧(饼)的起始角度start和终止角度end均为0

    2)绘制圆饼,6个不同板块,所以有6次for循环,从绘制第二个饼开始,起始角度是在上一个饼的终止角度位置,因此,每次循环开始后,要对当前的终止角度end进行累加一次,绘制圆弧直接以start开始,以end结束,当前绘制完成之后,要对起始角度start完成一次累加;同时每次绘制都给板块填充对应的颜色。封装为函数pieChart();

    3)绘制圆饼对应的占比数值,也是6次for循环,为了便于代码易读,这里重新定义了一个函数。并对起始角度start和终止角度end重新利用,nums中储存的是当前数值占100的份数,将其转化为对应角度为nums[i]/50*Math.PI;让其显示在板块角度中线位置nums[i]/50*Math.PI/2;同样每次循环起始角度是在上一个饼的终止角度位置,绘制前后也要进行累加。封装为函数pieNum();

    <canvas id="can1" width="800" height="600"></canvas>
        <script type="text/javascript">
                var can1 = document.getElementById("can1");
                var ctx = can1.getContext("2d");
                var nums = [26,15,12,5,25,17];
                var colors = ["#983335","#77963f","#5d437c","#35859f","#d1702f","#365e96"];
                var start = 0;
                var end = 0;
                ctx.translate(400,350);
                //绘制圆饼
                function pieChart(){
                    for (var i = 0;i < nums.length; i ++){
                        ctx.beginPath();
                        ctx.moveTo(0,0);
                        end += nums[i]/50*Math.PI;//终止角度
                        ctx.strokeStyle = "white";
                        ctx.fillStyle = colors[i];
                        ctx.arc(0,0,200,start,end);
                        ctx.fill();
                        ctx.closePath();
                        ctx.stroke();
                        start += nums[i]/50*Math.PI;//起始角度
                    }
                }
                //绘制圆饼上的数值
                function pieNum(){
                    for (var i = 0;i < nums.length; i ++){
                        start = nums[i]/50*Math.PI/2;
                        ctx.rotate(end+start);//旋转数值
                        ctx.font = "25px scans-serif";
                        ctx.fillStyle = "#000";
                        ctx.fillText(nums[i]+"%",140,0);
                        end = nums[i]/50*Math.PI/2;
                    }
                }
                ctx.rotate(-Math.PI/6);//旋转一定角度更加自然
                pieChart();
                pieNum();
    </script>

  • 相关阅读:
    课堂讨论电子版
    项目目标文档
    系统利益相关者
    实训八(游戏背景)
    实训七(项目准备与创建)
    实训六(Cocos2dx游戏分享到微信朋友圈----AppID的获取)
    实训五(Cocos2dx-3.x 打包apk再理解)
    实训四(cocos2dx sharesdk集成-1)
    实训三(cocos2dx 3.x 打包apk)
    实训二(cocos2dx 2.x 打包apk)
  • 原文地址:https://www.cnblogs.com/lmjZone/p/8808191.html
Copyright © 2011-2022 走看看