css实现圆形进度条加载动画

这里我会把遇到这个需求时的实现过程和遇到的问题记录下来,如果只是要看最终实现结果可直接滑到底部看实现代码。


我们经常可以看到网上有一些圆形进度条跟随数字的变化慢慢变成一个圆,这个动画实际上可以通过纯css来实现

通常情况下,我们实现这种结构只需要使用border-radius和padding就可以实现上图的样子,但是要实现动画,我们需要采取别的方式,这里要使用一个不常用的样式---clip(至少我在做这个动画前没使用过这个样式,不了解的可以上W3C clip样式看看)

首先我们要把中间的数字和动画分离开,中间的数字变化可以使用js的计数器来控制,动画则要由纯css来实现,可以通过after或者before来分离数字和圆弧。代码如下

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>test</title>
    <style>
        .time {
            display: inline-block;
            position: relative;
            width: 50px;
            height: 50px;
            line-height: 50px;
            text-align: center;
        }
        
        div::after {
            position: absolute;
            left: 0px;
            content: "";
            width: 50px;
            height: 50px;
            border: 1px solid #09f;
            border-radius: 50%;
        }
    </style>
</head>

<body>
    <div>
        <span class="time" id="time">10</span>
    </div>
    <script>
        var time = document.getElementById('time');
        count(0);

        function count(num) {
            time.innerHTML = num + '%';
            if (num < 100) {
                setTimeout(function() {
                    count(++num);
                }, 40)
            }
        }
    </script>
</body>

</html>

这样就把数字和圆分离了,然后接下来到我们的核心了,使用clip样式来切分我们要的部分

可是在切的时候我们发现,使用clip样式,我们能切的只能是一个矩形的内容块,切起来不是很方便,此时可以使用after和before来分别切分左半部分和右半部分。使用animation来实现动画,css代码修改如下

.time {
    display: inline-block;
    position: relative;
    width: 50px;
    height: 50px;
    line-height: 50px;
    text-align: center;
}

div::after {
    opacity: 0;
    position: absolute;
    left: 0px;
    content: "";
    width: 50px;
    height: 50px;
    border: 1px solid #09f;
    border-radius: 50%;
    animation: clipCircleLeft 2s linear 2s 1 forwards;
}

div::before {
    position: absolute;
    left: 0px;
    content: "";
    width: 50px;
    height: 50px;
    border: 1px solid #09f;
    border-radius: 50%;
    animation: clipCircleRight 2s linear 0s 1 forwards;
}

@keyframes clipCircleLeft {
    0% {
        opacity: 1;
        clip: rect(52px 26px 52px 0px);
    }
    100% {
        opacity: 1;
        clip: rect(0px 26px 52px 0px);
    }
}

@keyframes clipCircleRight {
    0% {
        clip: rect(0px 52px 0px 26px);
    }
    100% {
        clip: rect(0px 52px 52px 26px);
    }
}

这里要注意的是,clip切分区域时,总的切分长度是元素的宽度加上边框宽度*2。

这样做之后就可以看到流畅的进度条效果了,但是这样要同时使用after和before,而且一旦时间改变,要改变的地方也挺多的,如果用less或者sass还好,可以使用变量存储时间,直接使用css写的时候就有点烦了。而且before有时还要给字体图标使用,所以我想到了使用transform:rotate()来达到只是用before就可以实现圆形进度条动画效果。修改后的css代码如下

.time {
    display: inline-block;
    position: relative;
    width: 50px;
    height: 50px;
    line-height: 50px;
    text-align: center;
}

div::after {
    position: absolute;
    left: 0px;
    content: "";
    width: 50px;
    height: 50px;
    border: 1px solid #09f;
    border-radius: 50%;
    animation: clipCircle 4s linear 0s 1 forwards;
}

@keyframes clipCircle {
    0% {
        transform: rotateZ(90deg);
        clip: rect(0px 0px 52px 0px);
    }
    100% {
        transform: rotateZ(270deg);
        clip: rect(0px 52px 52px 0px);
    }
}

最终结果


同时使用before和after的例子

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>test</title>
    <style>
        .time {
            display: inline-block;
            position: relative;
            width: 50px;
            height: 50px;
            line-height: 50px;
            text-align: center;
        }
        
        div::after {
            opacity: 0;
            position: absolute;
            left: 0px;
            content: "";
            width: 50px;
            height: 50px;
            border: 1px solid #09f;
            border-radius: 50%;
            animation: clipCircleLeft 2s linear 2s 1 forwards;
        }
        
        div::before {
            position: absolute;
            left: 0px;
            content: "";
            width: 50px;
            height: 50px;
            border: 1px solid #09f;
            border-radius: 50%;
            animation: clipCircleRight 2s linear 0s 1 forwards;
        }
        
        @keyframes clipCircleLeft {
            0% {
                opacity: 1;
                clip: rect(52px 26px 52px 0px);
            }
            100% {
                opacity: 1;
                clip: rect(0px 26px 52px 0px);
            }
        }
        
        @keyframes clipCircleRight {
            0% {
                clip: rect(0px 52px 0px 26px);
            }
            100% {
                clip: rect(0px 52px 52px 26px);
            }
        }
    </style>
</head>

<body>
    <div>
        <span class="time" id="time">10</span>
    </div>
    <script>
        var time = document.getElementById('time');
        count(0);

        function count(num) {
            time.innerHTML = num + '%';
            if (num < 100) {
                setTimeout(function() {
                    count(++num);
                }, 40)
            }
        }
    </script>
</body>

</html>

只使用after和before其中一个的

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>test</title>
    <style>
        .time {
            display: inline-block;
            position: relative;
            width: 50px;
            height: 50px;
            line-height: 50px;
            text-align: center;
        }
        
        div::after {
            position: absolute;
            left: 0px;
            content: "";
            width: 50px;
            height: 50px;
            border: 1px solid #09f;
            border-radius: 50%;
            animation: clipCircle 4s linear 0s 1 forwards;
        }
        
        @keyframes clipCircle {
            0% {
                transform: rotateZ(90deg);
                clip: rect(0px 0px 52px 0px);
            }
            100% {
                transform: rotateZ(270deg);
                clip: rect(0px 52px 52px 0px);
            }
        }
    </style>
</head>

<body>
    <div>
        <span class="time" id="time">10</span>
    </div>
    <script>
        var time = document.getElementById('time');
        count(0);

        function count(num) {
            time.innerHTML = num + '%';
            if (num < 100) {
                setTimeout(function() {
                    count(++num);
                }, 40)
            }
        }
    </script>
</body>

</html>

 

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
您可以使用JavaScript和CSS来创建一个进度条加载网页动画,并在加载完成后自动跳转到百度网站。以下是一个示例代码: ```html <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>进度条加载网页动画</title> <style> #progress-bar { width: 100%; height: 10px; background-color: #f0f0f0; position: fixed; top: 0; left: 0; z-index: 9999; } #progress { width: 0%; height: 100%; background-color: #007bff; transition: width 0.5s ease-in-out; } </style> <script> window.onload = function() { var progressBar = document.getElementById("progress"); var interval = setInterval(function() { progressBar.style.width = progressBar.offsetWidth + 10 + "px"; if (progressBar.offsetWidth >= window.innerWidth) { clearInterval(interval); window.location.href = "https://www.baidu.com"; } }, 50); }; </script> </head> <body> <div id="progress-bar"> <div id="progress"></div> </div> </body> </html> ``` 在上述代码中,我们创建了一个进度条加载网页动画。当页面加载完毕后,通过 `window.onload` 事件触发的回调函数开始执行。我们使用 `setInterval` 方法定时更新进度条的宽度,每次增加10像素,直到进度条的宽度达到页面宽度时,清除定时器并将页面自动跳转到百度网站。 请确保将代码保存为HTML文件并在浏览器中打开运行。注意,由于跳转到其他网站是一种突然的行为,可能会被部分浏览器拦截,请确保浏览器设置允许自动跳转。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值