如何实现一个圆形波浪进度条的demo样式效果,具体效果参考下方效果GIF图。
页面效果图:
.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
属性的效果图:
.gif)
具体代码
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);
本文共 539 个字数,平均阅读时长 ≈ 2分钟
评论 (0)