说在前面
今天来实现一个水球进度加载动画效果,整体是一个球形容器,球顶不断有水滴滴落,随着水滴滴落,底部水位不断上升,水面上涨的同时伴随着波动的动画。
在线体验
码上掘金
codePen
代码实现
html
<div class="loader-container">
<div class="wave-loader">
<div class="wave wave1"></div>
<div class="wave wave2"></div>
<div class="percentage">0%</div>
</div>
</div>
- .loader-container:固定定位的全屏容器,用于覆盖整个页面,z-index: 9999确保层级最高
- .wave-loader:水球容器,圆形设计( border-radius: 50% ),内部包含:
- 两个 .wave 元素:双层波纹
- .percentage:实时显示进度的文本元素
水球容器
.wave-loader {
position: relative;
width: 200px;
height: 200px;
border-radius: 50%;
background: rgba(255, 255, 255, 0.1);
overflow: hidden;
box-shadow: 0 0 0 10px rgba(255, 255, 255, 0.05),
0 0 20px rgba(108, 92, 231, 0.3);
}
使用 box-shadow 添加一个外发光和内阴影效果。
波浪效果
.wave {
position: absolute;
width: 200%;
height: 200%;
top: 50%;
left: -50%;
transform-origin: 50% 50%;
animation: wave 6s linear infinite;
}
.wave1 {
background: rgba(108, 92, 231, 0.8);
border-radius: 45%;
animation-duration: 6s;
}
.wave2 {
background: rgba(0, 206, 255, 0.6);
border-radius: 40%;
animation-duration: 8s;
top: 60%;
}
设置不同的 border-radius 值,模拟不同形态的波浪(椭圆度差异),两层不同颜色的波浪形成了一个立体感。
波浪动画
.wave1 {
animation-duration: 6s;
}
.wave2 {
animation-duration: 8s;
}
@keyframes wave {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
给两个波浪加上旋转动画,两个动画的速度差可以让波浪更加有层次感。
加载进度
.percentage {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: white;
font-family: sans-serif;
font-size: 2rem;
font-weight: bold;
z-index: 10;
text-shadow: 0 0 10px rgba(255, 255, 255, 0.5);
}
通过 text-shadow 给文字简单加个发光效果。
水滴滴落动画
水滴和涟漪样式
.drop {
position: absolute;
width: 8px;
height: 12px;
transform-origin: center;
opacity: 0;
background: linear-gradient(
180deg,
rgba(0, 206, 255, 0.9),
rgba(108, 92, 231, 0.9)
);
border-radius: 50% 50% 50% 50% / 60% 60% 40% 40%;
box-shadow: 0 0 5px rgba(255, 255, 255, 0.3);
}
.ripple {
position: absolute;
border: 2px solid rgba(255, 255, 255, 0.3);
border-radius: 50%;
transform-origin: center;
opacity: 0;
}
创建水滴元素
function createDrop() {
const drop = document.createElement("div");
drop.style.left = `${Math.random()*80+10}%`; // 随机水平位置(10%-90%)
// 重力模拟动画
let velocity = 0, position = -15; // 初始位置在容器外上方
const waterLevel = 100 - progress; // 水面高度由进度决定
// 实时计算下落位置,到达水面后触发涟漪
if (position >= waterLevel * height / 100 - 5) {
createRipple(x, waterLevel); // 创建涟漪
}
}
涟漪效果
function createRipple(xPercent, y) {
const ripple = document.createElement("div");
// 涟漪扩散动画
ripple.style.width = ripple.style.height = "0"; // 初始尺寸为0
setTimeout(() => {
ripple.style.width = `${size}px`; // 逐渐扩大
ripple.style.opacity = 0; // 透明度渐变消失
}, 10);
}
源码
gitee
github
- 🌟 觉得有帮助的可以点个 star~
- 🖊 有什么问题或错误可以指出,欢迎 pr~
- 📬 有什么想要实现的功能或想法可以联系我~
公众号
关注公众号『 前端也能这么有趣 』,获取更多有趣内容。
发送 加群 还可以加入群聊,一起来学习(摸鱼)吧~
说在后面
🎉 这里是 JYeontu,现在是一名前端工程师,有空会刷刷算法题,平时喜欢打羽毛球 🏸 ,平时也喜欢写些东西,既为自己记录 📋,也希望可以对大家有那么一丢丢的帮助,写的不好望多多谅解 🙇,写错的地方望指出,定会认真改进 😊,偶尔也会在自己的公众号『
前端也能这么有趣
』发一些比较有趣的文章,有兴趣的也可以关注下。在此谢谢大家的支持,我们下文再见 🙌。