环形进度条(1)

408 阅读1分钟

环形进度条的模样

image.png

设计思路

// 将 圆分为两半, 画出两个半圆
// 超出部分 overflow: hidden, rotate(-45deg)
// 初始化时 先把 进度条 隐藏

html部分

  <div id="wrap">
    <div class="box-left">
      <div class="circle-left" ref="left"></div>
    </div>
    <div class="box-right">
      <div class="circle-right" ref="right"></div>
    </div>
    <div class="mark-box">
      <!-- 显示进度条数值的元素 -->
      <div class="number">{{percent}}</div>
    </div>
  </div>

css部分

#wrap{
  width: 200px;  // 总width200px
  height: 200px;
  margin: 20px auto;
  position: relative;
  border-radius: 50%;
}

/*底部圆圈*/
#wrap::before{
  content: "";
  position: absolute;
  width: 95%;
  height: 95%;
  box-sizing: border-box;
  left: 4px;
  top: 4px;
  border: 10px solid #F0BFC4;
  border-radius: 50%;
}
/*左右两个盒子里面各放着一个半圆圈,主要overflow*/
.box-left, .box-right{
  width: 50%;
  height: 100%;
  box-sizing: border-box;
  position: absolute;
  top: 0;
  overflow: hidden;
}
.box-left, .circle-left{
  left: 0;
}
.box-right, .circle-right{
  right: 0;
}
.circle-left, .circle-right{
  width: 200%;
  height: 100%;
  box-sizing: border-box;
  border: 20px #C40112 solid;
  border-radius: 50%;
  position: absolute;
  top: 0px;
}

/*左边盒子里的圆圈初始时只显示在右半边*/
.circle-left{
  border-top-color: transparent;
  border-left-color: transparent;
  transform: rotate(-45deg);
}
/*右边盒子里的圆圈初始时只显示在左半边*/
.circle-right{
  border-bottom-color: transparent;
  border-right-color: transparent;
  transform: rotate(-45deg);
}

js部分

initData () {
  let _this = this
  function go (target, total) {
    let that = _this
    let avg = div(target,total) // 总的平均数
    let progress = 0
    let now = 0
    // 用定时器模拟进度增长
    let progressAvg
    if(avg >= 0.5) {
      progress = div(total, 2)
      that.$refs.right.style.transform = 'rotate(135deg)'
    }
    let interVal = setInterval(() => {
      progress++
      progressAvg = div(progress, target) // 目标平均 (目前走动的进度 / 总的要走的target)
      requestAnimationFrame(grow)
      if (target <= progress) {
        clearInterval(interVal)
      }
    }, 10)
    function grow () {
      if (progress > target) {
        return;
      }
      // 如果进度数值有变化才做dom操作
      if (progress !== now) {
        now = progress;
        // deg : 360 块
        let deg = (360 * avg) * progressAvg
        if (avg < 0.5) { // 小于半圆
          that.$refs.right.style.transform = `rotate(${deg - 45}deg)`
          // that.$refs.left.style.transform = 'rotate(-45deg)'
        } else if (avg === 0.5) {
          that.$refs.right.style.transform = 'rotate(135deg)'
        } else if (avg >= 0.5 && avg < 1) { // 如果进度值大于50,那就左边半圆转动
          that.$refs.left.style.transform = `rotate(${deg - 225}deg)`
        } else if (avg >= 1) {
          that.$refs.left.style.transform = 'rotate(135deg)'
          that.$refs.right.style.transform = 'rotate(135deg)'
        }
      }
    }
    }
    go(this.target, this.total);
  }