慕课网实战—《用组件方式开发 Web App全站 》笔记七-饼图和环图组件开发

运用HTML5、CSS3、JS流行技术,采用组件式开发模式,开发Web App全站!技术大牛带你统统拿下不同类型的HTML5动态数据报告!
《用组件方式开发 Web App全站 》

饼图开发(绘制饼图准备)

  • 饼图实现原理
    这里写图片描述

饼图开发(绘制饼图)

  • 代码
/* 饼图组件对象 */

var H5ComponentPie =function ( name, cfg ) {
  var component =  new H5ComponentBase( name ,cfg );

  //  绘制网格线 - 背景层
  var w = cfg.width;
  var h = cfg.height;

  //  加入一个画布(网格线背景)
  var cns = document.createElement('canvas');
  var ctx = cns.getContext('2d');
  cns.width = ctx.width = w;
  cns.height = ctx.height =h;
  $(cns).css('zIndex',1);
  component.append(cns);

  var r =w/2;

  //  加入一个底图层
  ctx.beginPath();
  ctx.fillStyle='#eee';
  ctx.strokeStyle='#eee';
  ctx.lineWidth = 1;
  ctx.arc(r,r,r,0,2*Math.PI);
  ctx.fill();
  ctx.stroke();

  //  绘制一个数据层
  var cns = document.createElement('canvas');
  var ctx = cns.getContext('2d');
  cns.width = ctx.width = w;
  cns.height = ctx.height =h;
  $(cns).css('zIndex',2);
  component.append(cns);

  var colors = ['red','green','blue','#a00','orange']; //  备用颜色
  var sAngel = 1.5 * Math.PI; //  设置开始的角度在 12 点位置
  var eAngel = 0; //  结束角度
  var aAngel = Math.PI*2; //  100%的圆结束的角度 2pi = 360


  var step = cfg.data.length;
  for(var i=0;i<step;i++){

    var item  = cfg.data[i];
    var color = item[2] || ( item[2] = colors.pop() );

    eAngel = sAngel + aAngel * item[1];

    ctx.beginPath();
    ctx.fillStyle=color;
    ctx.strokeStyle=color;
    ctx.lineWidth = .1;

    ctx.moveTo(r,r);
    ctx.arc(r,r,r,sAngel,eAngel);
    ctx.fill();
    ctx.stroke();
    sAngel = eAngel;


    //  加入所有的项目文本以及百分比

    var text = $('<div class="text">');
    text.text( cfg.data[i][0] );
    var per =  $('<div class="per">');
    per.text( cfg.data[i][1]*100 +'%'  );
    text.append(per);

    var x = r + Math.sin( .5 * Math.PI - sAngel ) * r;
    var y = r + Math.cos( .5 * Math.PI - sAngel ) * r;

    // text.css('left',x/2);
    // text.css('top',y/2);

    if(x > w/2){
      text.css('left',x/2);
    }else{
      text.css('right',(w-x)/2);
    }
    if(y > h/2){
      text.css('top',y/2);
    }else{
      text.css('bottom',(h-y)/2);
    }
    if( cfg.data[i][2] ){
      text.css('color',cfg.data[i][2]); 
      // text.css('color','#fff'); 
      // text.css('backgroundColor',cfg.data[i][2]); 
    }
    text.css('opacity',0);
    component.append(text);

  }

   //  加入一个蒙板层
  var cns = document.createElement('canvas');
  var ctx = cns.getContext('2d');
  cns.width = ctx.width = w;
  cns.height = ctx.height =h;
  $(cns).css('zIndex',3);
  component.append(cns);


  ctx.fillStyle='#eee';
  ctx.strokeStyle='#eee';
  ctx.lineWidth = 1;

}
  • 实现效果
    这里写图片描述

饼图开发(绘制饼图动画)

//  生长动画

  var draw = function( per ){

    ctx.clearRect(0,0,w,h);

    ctx.beginPath();

    ctx.moveTo(r,r);

    if(per <=0){
      ctx.arc(r,r,r,0,2*Math.PI);
      component.find('.text').css('opacity',0)
    }else{
      ctx.arc(r,r,r,sAngel,sAngel+2*Math.PI*per,true);
    }

    ctx.fill();
    ctx.stroke();

    if( per >= 1){
      component.find('.text').css('transition','all 0s');
      H5ComponentPie.reSort( component.find('.text') );
      component.find('.text').css('transition','all 1s');
      component.find('.text').css('opacity',1);
      ctx.clearRect(0,0,w,h);
    }
  }
  draw(0);

  component.on('onLoad',function(){
    //  饼图生长动画
      var s = 0;
      for( i=0;i<100;i++){
        setTimeout(function(){
            s+=.01;
            draw(s);
        },i*10+500);
      }
  });
  component.on('onLeave',function(){
    //  饼图退场动画
      var s = 1;
      for( i=0;i<100;i++){
        setTimeout(function(){
            s-=.01;
            draw(s);
        },i*10);
      }
  });

  return component;
}

饼图开发(项目文本注入)

//  重排项目文本元素
H5ComponentPie.reSort = function( list ){

  //  1. 检测相交
  var compare = function( domA, domB ){

    //  元素的位置,不用 left,因为有时候 left为 auto
    var offsetA = $(domA).offset();
    var offsetB = $(domB).offset();

    //  domA 的投影
    var shadowA_x = [ offsetA.left,$(domA).width()  + offsetA.left ];
    var shadowA_y = [ offsetA.top ,$(domA).height() + offsetA.top ];

    //  domB 的投影
    var shadowB_x = [ offsetB.left,$(domB).width()  + offsetB.left ];
    var shadowB_y = [ offsetB.top ,$(domB).height() + offsetB.top  ];

    //  检测 x
    var intersect_x = ( shadowA_x[0] > shadowB_x[0] && shadowA_x[0] < shadowB_x[1] ) || ( shadowA_x[1] > shadowB_x[0] &&  shadowA_x[1] < shadowB_x[1]  );

    //  检测 y 轴投影是否相交
    var intersect_y = ( shadowA_y[0] > shadowB_y[0] && shadowA_y[0] < shadowB_y[1] ) || ( shadowA_y[1] > shadowB_y[0] &&  shadowA_y[1] < shadowB_y[1]  );
    return intersect_x && intersect_y;
  }


  //  2. 错开重排
  var reset = function( domA, domB ){

    if( $(domA).css('top') != 'auto' ){

      $(domA).css('top', parseInt($(domA).css('top')) + $(domB).height() );
    }
    if( $(domA).css('bottom') != 'auto' ){

      $(domA).css('bottom', parseInt($(domA).css('bottom')) + $(domB).height() );
    }

  }

  //  定义将要重排的元素
  var willReset = [list[0]];

  $.each(list,function(i,domTarget){
    if( compare(willReset[willReset.length-1] , domTarget ) ){
      willReset.push(domTarget);  //  不会把自身加入到对比
    }
  });

  if(willReset.length >1 ){
      $.each(willReset,function(i,domA){
          if( willReset[i+1] ){
            reset(domA,willReset[i+1]);
          }
      });
      H5ComponentPie.reSort( willReset );
  }

HTML&CSS

  • HTML
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8"/>
    <meta name="viewport" content="width=device-width, minimum-scale=1, maximum-scale=1">

    <title>IT教育网2015课程学习情况</title>

    <style type="text/css">
        body{
            margin: 0;
            padding: 0;
            background-color: #000;
            font-size: 12px;
        }

        .iPhone{
            width: 340px;
            height: 540px;
            background-color: #fff;
            position: absolute;
            left: 50%;
            top: 50%;
            margin: -270px 0 0 -170px;
        }
    </style>

    <script type="text/Javascript" src="../js/lib/jquery.js"></script>
    <script type="text/javascript" src="../js/H5ComponentBase.js"></script>
    <link rel="stylesheet" type="text/css" href="../css/H5ComponentBase.css">


    <!-- 引入饼图的资源 -->
    <script type="text/javascript" src="../js/H5ComponentPie.js"></script>
    <link rel="stylesheet" type="text/css" href="../css/H5ComponentPie.css">

    <body>
        <!-- 用于开发测试 H5ComponentPie 对象(饼图组件) -->
        <div class="iphone">

        </div>

        <script type="text/javascript">

            var cfg = {
                type : 'pie',

                width : 400,
                height : 400,

                data:[
                    ['Js' , .7  ,'#ff7676'],
                    ['CSS3' , .05 ],
                    ['HTML5' , .05  ],
                    ['PHP' , .05  ],
                    ['jQuery' , .15 ]
                ],
                css : {
                    top:100,
                    opacity:0
                },
                animateIn:{
                    opacity:1,
                    top:200,
                },
                animateOut:{
                    opacity:0,
                    top:100,
                },
                center : true,
            }

            var h5 = new H5ComponentPie( 'myBarComponent', cfg );
            $('.iphone').append(h5);


            var leave = true;
            $('body').click(function (){
                leave = !leave;
                $('.h5_component').trigger( leave ? 'onLeave' : 'onLoad' )
            }).click();

        </script>

    </body>

</html>
  • CSS
/* 饼图组件样式 */

.h5_component_pie{
}

.h5_component_pie canvas{
    position: absolute;
    left: 0;
    top: 0; /* 用canvas做动画,会进行分层,要用到  z-index */
    width: 100%;
    height: 100%;
}

.h5_component_pie .text{
    position: absolute;
    z-index: 99;
    font-size: 12px;
    text-align: center;
    height: 24px;
    transition:all 10s;
}

饼图效果

????这里写图片描述

H5ComponentPie扩展,环图实现

  • 区别
    ????这里写图片描述

  • 步骤提示

??环图只支持一个数据、需要预先格式化;环图就是在饼图中间增加一个圆形的白色遮罩,并且把项目文本、百分比,添加到遮罩中,水平垂直居中,完成!

一:在 HTML 中引入必要的资源文件,并且完成配置以及实例化的代码
分析:
??1、需要引入必要的资源,包括 jquery.js、H5componentBase 相关资源(css、js)、H5ComponentPie 相关资源(css、js),环图自身的资源(css、js)共计 7 个文件。
??2、配置文件缺少类型 (type) 和数据 (data) 的定义,完成这两个配置。
注意:环图只支持一项数据
??3、完成 组件对象 (h5) 的定义(var h5 = …??),注意这里 new 的对象是 环图组件对象

二:在 JS 中 完成环图的逻辑
分析:
??1、把数据格式化为只有一项,例如 a = [ [1] , [2] , [3] ] 格式化为: a=[ [1] ]
??2、重设配置中的 type 参数 (cfg.type=’pie’;),不仅利用 H5ComponentPie 构建 DOM 结构和 JS 逻辑,也使用其 CSS 样式定义(思考下为什么能达到这个效果?)
??3、修正组件的样式,以支持在样式文件中组件的样式定义 .h5_component_ring 相关样式能生效
??4、把创建好的遮罩元素 (.mask) 添加到组件中
??5、在遮罩元素 ( .mask ) 中添加项目文本信息

三:完善环图的样式
分析:
??1、修正遮罩层的样式,为其添加白色背景颜色,并且设置为完成 圆形饼图的 80% 大小
??2、注意:把遮罩层设置为圆形的方式是通用方法:border- radius:50%
??3、注意:把遮罩层设置为 饼图的 80% 大小,可修改宽度配合 left、top 也可以使用 scale

JS代码

/* 环图组件对象 */

var H5ComponentRing =function ( name, cfg ) {


  if(cfg.data.length>1){  //  环图应该只有一个数据
    // 任务二:(1) 把数据格式化为只有一项,例如 a = [ [1] , [2] , [3] ] 格式化为: a=[ [1] ]
    cfg.data = http://blog.csdn.net/lovejulyer/article/details/[cfg.data[0]];
  }

  //  任务二:(2) 重设配置中的 type 参数,不仅利用 H5ComponentPie 构建 DOM 结构和 JS 逻辑,也使用其 CSS 样式定义(思考下为什么能达到这个效果)
  cfg.type = 'pie';
  var component =  new H5ComponentPie( name ,cfg );

  //  任务二:(3) 修正组件的样式,以支持在样式文件中组件的样式定义 .h5_component_ring 相关样式能生效
  component.addClass('h5_component_ring');


  var mask = $('<div class="mask">');

  // 任务二:(4) 把创建好的遮罩元素添加到组件中
  component.append(mask);

  var text = component.find('.text');

  text.attr('style','');
  if(cfg.data[0][2]){
    text.css('color',cfg.data[0][2]);
  }
  //  任务二:(5) 在遮罩元素( .mask ) 中添加文本信息
  mask.append( text );

  return component;
}

CSS改动

/* 环图组件样式 */

.h5_component_ring{
}

.h5_component_ring .mask{
    width: 100%;
    height: 100%;
    position: absolute;
    left: 0;
    top: 0;
    z-index: 90;
    /* 任务三:修正遮罩层的样式,为其添加白色背景颜色,并且设置为完成 圆形饼图的 80% 大小 */
    background-color: #fff;
    border-radius: 50%;
    -webkit-transform:scale(.8);
}

.h5_component_ring .text{
    width: 100%;
    top: 40%;
    opacity: 0;
}
.h5_component_ring .text .per{
}

环图实现效果

????这里写图片描述

赞 (0) 评论 分享 ()