一、简介
本篇博客讲述了如何实现一个圆形波浪进度条的样式效果,具体效果参考下方GIF图。该样式的加载进度条可以用在页面跳转或数据处理等情况下的加载动画,比起普通的横条进度条来说,样式效果更生动美观。
实现思路:
这个样式效果看似很简单,实际上实现起来一点也不难。难的是如何想到实现的思路。
① 外层父元素通过border-radius
,变成圆形,并设置其position: ralative;
和overflow: hidden;
,使其内部超出的部分被隐藏。
② 在内部创建一个子元素,作为实现波浪效果的元素,设置其宽高为父元素的两倍,并通过border-radius
设置其圆角。
③ 给该子元素设置一个旋转动画,使其循环播放,一直旋转。并通过position: absolute;
使子元素的顶部对齐父元素的底部。
④ 设置一个CSS自定义属性--progress
,通过top: calc(100% - var(--progress));
控制子元素的在Y轴上的移动。在JS中可以通过控制--progress
的数值,来控制子元素向上移动距离,从而表现整体进度的百分比。由于父元素设置了overflow: hidden;
,所以在子元素旋转上移的过程中,只有一部分内容能在父元素内容区域中显示出来,再加上子元素的旋转+圆角样式,就形成了波浪的效果。
⑤ 再创建一个子元素,内部文本显示进度的百分比数字,该子元素同样通过absolute
进行绝对定位,使其位于父元素中间,并且z-index
的层级大于上面的波浪元素。
页面效果图:
overflow: hidden
属性的效果图:
帮助理解,去除掉二、具体代码
CSS代码:
/* 定一个旋转动画 用于实现波浪效果 */
@keyframes progressRotate {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
/* 设置外层元素样式 */
.progress-box {
position: relative;
width: 200px;
height: 200px;
border-radius: 50%;
background: #fff;
/* 最关键的属性 */
overflow: hidden;
}
/* 设置进度条样式 */
.progress {
position: absolute;
/* 波浪占据外层圆形区域的百分比 由 --progress控制 */
top: calc(100% - var(--progress));
left: 50%;
transform: translateX(-50%);
z-index: 9;
width: 200%;
height: 200%;
border-radius: 34%;
background: #6495ED;
/* 添加旋转动画效果 */
animation: progressRotate 2.5s linear infinite;
/* 由于上面使用了transform 且动画中也使用了transform 设置该属性使其叠加生效 */
animation-composition: add;
}
/* 设置进度数字样式 */
.number {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 10;
margin: 0;
font-size: 24px;
}
html代码:
<!-- 圆形波浪进度条外层元素 -->
<div class="progress-box">
<!-- 波浪效果元素 设置了一个css变量 -->
<div class="progress" style="--progress: 0%"></div>
<!-- 进度数字 -->
<p class="number">0%</p>
</div>
JavaScript代码:
// 获取进度条元素
const progress = document.querySelector('.progress');
const number = document.querySelector('.number');
// 进度值
let progressValue = 0;
// 模拟获取进度
let timer = setInterval(() => {
progressValue += 1;
// 更新波浪进度条的进度
progress.style.setProperty('--progress', `${progressValue}%`);
// 更新进度数字
number.textContent = `${progressValue}%`;
// 记得清除定时器
if (progressValue === 100) {
clearInterval(timer);
}
}, 40);