CSS3简单写个圆形进度条动画

萝らか妹 提交于 2020-01-17 22:29:19

圆圈转动完整代码

html

<div id="wrap">
    <div class="box-left">
        <div class="circle-left"></div>
    </div>
    <div class="box-right">
        <div class="circle-right"></div>
    </div>
</div>

css

#wrap{
  width: 200px;
  height: 200px;
  margin: 200px auto;
  position: relative;
  border-radius: 50%;
}
 
/*底部圆圈*/
#wrap::before{
  content: "";
  position: absolute;
  width: 100%;
  height: 100%;
  box-sizing: border-box;
  left: 0;
  top: 0;
  border: 10px solid rgba(255,255,255,0.5);
  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: 10px blue solid;
  border-radius: 50%;
  position: absolute;
  top: 0;
}
 
/*左边盒子里的圆圈初始时只显示右半边*/
.circle-left{
  border-top-color: transparent;
  border-left-color: transparent;
  transform: rotate(-45deg);
  animation: circleRotate 2s linear forwards 2s;
}
/*右边盒子里的圆圈初始时只显示左半边*/
.circle-right{
  border-bottom-color: transparent; 
  border-right-color: transparent; 
  transform: rotate(-45deg);
  animation: circleRotate 2s linear forwards;
}
@keyframes circleRotate{
  from {transform: rotate(-45deg)}
  to {transform: rotate(135deg)}
}

效果

 

为了更像进度条做些扩展

html

先在html中加上显示进度数值的元素,及进度条完成时弹出对勾的元素。

<div id="wrap">
    <div class="box-left">
        <div class="circle-left"></div>
    </div>
    <div class="box-right">
        <div class="circle-right"></div>
    </div>
    <div class="mark-box">
        <!-- 显示进度条数值的元素 -->
        <div class="number"></div>
        <!-- 进度条完成时弹出的对勾 -->
        <div class="checkmark"></div>
    </div>
</div>

css

接着上面的css继续写,先注释掉上面的 animation (因为接下来要用js来完成动画)。

/*新加元素的样式*/
.mark-box{
  width: 40%;
  height: 30%;
  /*background-color: red;*/
  position: absolute;
  left: 30%;
  top: 35%;
  color: white;
  font-size: 30px;
  text-align: center;
  line-height: 2em;
}
.checkmark{
  width: 100%;
  height: 100%;
  /*background-color: yellow;*/
  position: absolute;
  top: 0;
  left: 0;
  transform: rotate(-45deg) translate(13%, -10%);
}
.checkmark::before, .checkmark::after{
  content: "";
  background-color: white;
  position: absolute;
  left: 0;
}
.checkmark::before{
  width: 5px;
  height: 0;
  top: 0;
  transition: all 0.15s;
}
.checkmark::after{
  width: 0;
  height: 5px;
  bottom: 0;
  transition: all 0.15s 0.15s;
}
.checkmark.active::before{
  height: 100%;
}
.checkmark.active::after{
  width: 100%;
}

js

用 requestAnimationFrame 完成动画

let circleLeft = document.querySelector('.circle-left');
      let circleRight = document.querySelector('.circle-right');
      let checkmark = document.querySelector('.checkmark');
      let textNode = document.querySelector('.mark-box > .number');
      
      function go(start, target){
        //如果进度值初始就大于50,就把右边半圆先填满
        if(start >= 50){              
          circleRight.style.transform = 'rotate(135deg)';
        }
        let progress = start;
        let now = start;
        
        //用定时器模拟进度增长
        setInterval(() => {
          progress++;
        }, 100)
        
        let num = 0;  //测试标记
        function grow(){
          console.log('lala', ++num)  //测试标记
          
          if(progress > target){
            return;
          }
          
          //如果进度数值有变化才做dom操作
          if(progress !== now){
            now = progress;
            let deg = (180/50)*progress;  
            //进度数值显示
            textNode.textContent = progress;
            
            //如果进度值小于50,那就右边半圆转动
            if(progress <= 50){
              console.log('dom')  //测试标记              
              circleRight.style.transform = `rotate(${deg-45}deg)`;
              
            }else if(progress > 50){//如果进度值大于50,那就左边半圆转动
              console.log('dom')  //测试标记
              circleLeft.style.transform = `rotate(${deg-180-45}deg)`;
              
              //如果进度值达到100了,那就弹出对勾
              if(progress === 100){
                textNode.style.display = 'none';
                checkmark.classList.add('active');
                console.log('done');
                return;
              }
            }
          }
          
          
          requestAnimationFrame(grow);
        }
        requestAnimationFrame(grow);
      }
      
      go(0, 108)

最终效果

 

 

 

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!