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

圆圈转动完整代码

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);

最终效果

发布了63 篇原创文章 · 获赞 18 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/samfung09/article/details/104024958