描述

实现一个border为8px的不完整圆环进度条,小于50%进度条颜色为#97d3ff,大于50%进度条颜色为#0094ff。

原理

  1. 画一个宽144px高144px的方形;
  2. 方形中画两个等大均分方形的矩形宽72px高144px,(注意每个矩形一定要设置:overflow:hidden),css中的right left样式;
  3. 进度条由两个叠加环形组成,所以第一步的方形中需要画四个等大的矩形用来展示不同部分的环形 under下的rightcircle,leftcircle up下的 rightcircle,leftcircle四个
  4. 每个矩形中画一个和父级方形等大的方形,用来展示环形,左半矩形中的环形只设置上边框和左边框;右半矩形中的环形只设置上边框和右边框;
  5. 实现进度条的动态百分比进度,使用css3的transform:rotate将上叠加环形根据实际百分比换算成实际的旋转角度来实现。
    当剩余量大于50%时左侧上叠加环形旋转角度不用变,只有计算右测上叠加环形旋转角度即可。
    当剩余量小于百分之50%时,左侧上叠加环形旋转时,就会将左半环形展示为完整的半环,此时就需要一个用来遮挡左侧超出进度范围环形部分的左侧环 up_left_cover

html代码

<div class="progress_wrap" :class="giftCircleProgressFn(5).halfClassName">
     <div class="right under">
         <div class="circleProgress rightcircle"></div>
     </div>
     <div class="left under">
         <div class="circleProgress leftcircle"></div>
     </div>
     <div class="right up">
         <div class="circleProgress rightcircle" :style="{transform:'rotate('+giftCircleProgressFn(5).rightRotate.toString()+'deg)'}"></div>
     </div>
     <div class="left up">
         <div class="circleProgress leftcircle" :style="{transform:'rotate('+giftCircleProgressFn(5).leftRotate.toString()+'deg)'}"></div>
     </div>
     //percent小于50时需要使用遮罩进行遮挡超出环形范围部分
     <div class="left up_left_cover" :style="{display:giftCircleProgressFn(5).leftCircleDisplay}">
         <div class="circleProgress leftcircle"></div>
     </div>
     <div class="num">
         {{giftCircleProgressFn(5).percent}}%
     </div>
 </div>

css代码

//进度条样式
.progress_wrap{
  position: relative;
  margin:0 0 0 14px;
  width:144px;
  height:144px;
  margin: 0 auto;
  margin-top: 30px;
  margin-bottom: 10px;
  //little和more用来展示黄色和绿色的效果
  &.little{
    .under{
      .rightcircle,.leftcircle{
        border-top:8px solid #D7E3F2;
      }
      .rightcircle{
        border-right:8px solid #D7E3F2;
      }
      .leftcircle{
        border-left:8px solid #D7E3F2;
      }
    }
    .up{
      .rightcircle,.leftcircle{
        border-top:7px solid #97D3FF;
      }
      .rightcircle{
        border-right:10px solid #97D3FF;
      }
      .leftcircle{
        border-left:8px solid #97D3FF;
      }
    }
    //用遮挡实现左侧剩余百分比,遮住超出环形范围部分;核心是使用同心圆进行边框进行遮挡
    .up_left_cover{
      width:72px;
      height:144px;
      .leftcircle{
        top:0px;
        width:122px;
        height:122px;
        border:10px solid transparent;
        border-top:13px solid #fff;
        border-left:12px solid #fff;
        //实际值为195deg,被遮挡环颜色值深有光晕,需要将角度进行微调(-191deg)进行完全遮挡
        -webkit-transform:rotate(-189deg);
      }
    }
  }
  &.more{
    .under{
      .rightcircle,.leftcircle{
        border-top:8px solid #D7E3F2;
      }
      .rightcircle{
        border-right:8px solid #D7E3F2;
      }
      .leftcircle{
        border-left:8px solid #D7E3F2;
      }
    }
    .up{
      .rightcircle,.leftcircle{
        border-top:8px solid #0094FF;
      }
      .rightcircle{
        border-right:8px solid #0094FF;
      }
      .leftcircle{
        border-left:8px solid #0094FF;
      }
    }
  }
  .right,.left{
    position: absolute;
    top:0;
    overflow:hidden;
    width:72px;
    height:144px;
    .circleProgress{
      position: absolute;
      top:0;
      width: 122px;
      height: 122px;
      border:13px solid transparent;
      border-radius: 50%;
    }
    .rightcircle{
      right:0;
      -webkit-transform: rotate(15deg);
    }
    .leftcircle{
      left:0;
      -webkit-transform: rotate(-15deg);
    }
  }
  .right{
    right:0;
  }
  .left{
    left:0;
  }
  .num{
    position: absolute;
    left:50%;
    top:50%;
    transform:translate(-50%,-50%);
    font-size:17px;
    color:rgba(153,153,153,1);
    line-height:23px;
    text-align:center;
  }
}

js代码

giftCircleProgressFn : function(per){
    let vm = this;
    let circleData = {};
    let percent = parseInt(per);
    //领取进度环形颜色className
    let halfClassName = percent<50?"little":"more";
    //左半环遮罩层显示样式状态
    let leftCircleDisplay = percent<50?"block":"none";
    let leftRotate = 0;
    let rightRotate = 0;
    //以50%为界限;<50%:右半圆占比为0,左半圆需要使用遮罩进行遮挡,展示剩余部分
    //           >50%:左半圆占比100%,右半圆直接使用百分比计算所占部分即可
    //注意:在半圆中计算百分比时,要将百分比乘以2。
    if(percent<50){
        leftRotate = -180+150*(percent*2)/100;
        rightRotate = -135;
    }else{
        leftRotate = -15;
        rightRotate = -135+(150*((percent-50)*2)/100);   //比例在半环计算需要*2倍
    }
    circleData = {
        leftRotate:leftRotate,  //左半环进度
        rightRotate:rightRotate, //右半环进度
        halfClassName:halfClassName, //50% 进度环 变色
        leftCircleDisplay:leftCircleDisplay, //左半环遮罩
        percent:per  //进度百分比
    };
    return circleData
}

效果图

swift 环形进度 实现 前端环形进度条_ci


swift 环形进度 实现 前端环形进度条_css_02


swift 环形进度 实现 前端环形进度条_vue.js_03