涨姿势了,有意思的气泡 Loading 效果

打印 上一主题 下一主题

主题 1680|帖子 1680|积分 5042

今日,群友提问,如何实现这么一个 Loading 效果:

这个确实有点意思,但是这是 CSS 能够完成的?
没错,这个效果中的核心气泡效果,其实借助 CSS 中的滤镜,能够比较轻松的实现,就是所需的元素可能多点。参考我们之前的:
圆弧的实现

首先,我们可能需要实现这样一段圆弧:

这里需要用到的技术是:
角向渐变 conic-gradient() + mask 以及两个伪元素。图片示意如下:

核心代码如下图:
  1.   
复制代码
  1. :root {
  2.     --headColor: hsl(130, 75%, 75%);
  3.     --endColor: hsl(60, 75%, 40%);
  4. }
  5. .g-container {
  6.     position: relative;
  7.     background: #000;
  8. }
  9. .g-circle {
  10.     position: relative;
  11.     width: 300px;
  12.     height: 300px;
  13.     border-radius: 50%;
  14.     background: conic-gradient(
  15.         var(--headColor) 0,
  16.         var(--headColor) 10%,
  17.         hsl(120, 75%, 70%),
  18.         hsl(110, 75%, 65%),
  19.         hsl(100, 75%, 60%),
  20.         hsl(90, 75%, 55%),
  21.         hsl(80, 75%, 50%),
  22.         hsl(70, 75%, 45%),
  23.         var(--endColor) 30%,
  24.         var(--endColor) 35%,
  25.         transparent 35%
  26.     );
  27.     mask: radial-gradient(transparent, transparent 119px, #000 120px, #000 120px, #000 100%);
  28.    
  29.     &::before,
  30.     &::after {
  31.         content: "";
  32.         position: absolute;
  33.         inset: 0;
  34.         width: 30px;
  35.         height: 30px;
  36.         background: var(--headColor);
  37.         top: 0;
  38.         left: 135px;
  39.         border-radius: 50%;
  40.     }
  41.    
  42.     &::after {
  43.         background: var(--endColor);
  44.         left: unset;
  45.         top: 214px;
  46.         right: 26px;
  47.     }
  48. }
复制代码
这样,我们就得到了这样一个图形:

气泡的实现

接下来,我们来实现尾部气泡向外扩散的效果。
由于这里涉及了多个气泡的不同运动动画,多个标签元素肯定是少不了了。
因此,接下来我们要做的事情:

  • 我们需要多一组元素,将其绝对定位到上述圆环的头部或者尾部
  • 给每个子元素随机设置多个大小不一的圆,颜色保持一致
  • 给每个子元素随机设置不同方向的,向外扩散的位移动画
  • 给每个子元素随机设置负的 animation-delay,造成动画上的先后顺序,并以此形成整个无限循环的气泡扩散动画
这里,由于有许多小气泡的动画,这个数量,我设置成了 100。那肯定是不能一个一个手写它们的动画代码,需要借助 SASS/LESS 等预处理器的循环、随机等函数。
核心代码如下:
  1.   
  2.   <ul >
  3.     <li ></li>
  4.     // ... 共 100 个 bubble 元素
  5.     <li ></li>
  6.   </ul>
复制代码
  1. // 上面圆环的代码,保持一致,下面只补充气泡动画的代码
  2. .g-bubbles {
  3.     position: absolute;
  4.     width: 30px;
  5.     height: 30px;
  6.     border-radius: 50px;
  7.     top: 100px;
  8.     left: 235px;
  9.     background: var(--headColor);
  10. }
  11. .g-bubble {
  12.     position: absolute;
  13.     border-radius: 50%;
  14.     background-color: inherit;
  15. }
  16. @for $i from 1 through 100 {
  17.     .g-bubble:nth-child(#{$i}) {
  18.         --rotate: calc(#{random(360)} * 1deg);
  19.         --dis: calc(#{random(100)} * 1px);
  20.         --width: calc(3px + #{random(25)} * 1px);
  21.         top: 50%;
  22.         left: 50%;
  23.         transform: translate(-50%, -50%);
  24.         width: var(--width);
  25.         height: var(--width);
  26.         animation: move #{(random(1500) + 1500) / 1000}s ease-in-out -#{random(3000) / 1000}s infinite;
  27.     }
  28. }
  29. @keyframes move {
  30.     0% {
  31.         transform: translate(-50%, -50%) rotate(0deg);
  32.     }
  33.     75% {
  34.         opacity: .9;
  35.     }
  36.     100% {
  37.         transform: rotateZ(var(--rotate)) translate(-50%, var(--dis));
  38.         opacity: .4;
  39.     }
  40. }
复制代码
核心在于 @for $i from 1 through 100 { } 这段 SASS 代码内部,我们实现了上面说的 (2)(3)(4) 的功能点!
这样,我们就得到了这样一个效果,在尾部有大量气泡动画,不断向外扩散的效果:

借助滤镜实现粘性气泡效果

OK,到这里整个效果基本就做完了。当然,也是剩下最后最重要的一步,需要让多个气泡之间产生一种粘性融合的效果。
这个技巧在此前非常多篇文章中,也频繁提及过,就是利用 filter: contrast() 滤镜与 filter: blur() 滤镜。
如果你还不了解这个技巧,可以戳我的这篇文章看看:你所不知道的 CSS 滤镜技巧与细节
简述下该技巧:
单独将两个滤镜拿出来,它们的作用分别是:

  • filter: blur(): 给图像设置高斯模糊效果。
  • filter: contrast(): 调整图像的对比度。
但是,当他们“合体”的时候,产生了奇妙的融合现象。

仔细看两圆相交的过程,在边与边接触的时候,会产生一种边界融合的效果,通过对比度滤镜把高斯模糊的模糊边缘给干掉,利用高斯模糊实现融合效果。
基于此,我们再简单改造下我们的 CSS 代码,所需要加的代码量非常少:

  • 加上滤镜 blur() 和 contrast() ,形成融合粘性效果
  • 加上整个圆环的旋转即可效果
  • 加上滤镜 hue-rotate(),实现色彩的变换动画
  1. .g-container {
  2.     // ... 保持一致
  3.     background: #000;
  4.     filter: blur(3px) contrast(5);
  5.     animation: rotate 4s infinite linear;
  6. }
  7. @keyframes rotate {
  8.     100% {
  9.         transform: rotate(360deg);
  10.         filter: blur(3px) contrast(5) hue-rotate(360deg);
  11.     }
  12. }
复制代码
就这样,我们就大致还原了题图的效果:

完整的代码,你可以戳这里:CodePen Demo -- Pure CSS Loading Animation
修复违和感

当然,上面的效果,乍一看还行,仔细看,违和感很重。
原因在于,扩散出来的小球也跟着半圆环一起进行了旋转动画,看上去就有点奇怪。
正确的做法应该是,圆环尾部的气泡应该是原地发散消失的。
那么,怎么能够做到气泡效果,一直发生在圆环的尾部,同时消失的时候又不跟着整个圆环一起进行旋转呢?我们想要的最终效果,应该是这样:

这里,我们可以拆解一下。想象,如果去掉圆环的旋转,其实我们只需要实现这样一个效果即可:

整个动画的核心就转变成了如何实现这么一个效果。看似复杂,其实也很好做。
首先,我们重新改造一下上述的 .g-bubbles。

  • 生成 N 个一样大小的小球元素,定位在整个容器的中间
  1.   
  2.   <ul >
  3.     <li ></li>
  4.     // ... 共 200 个 bubble 元素
  5.     <li ></li>
  6.   </ul>
复制代码
  1. .g-bubbles {
  2.     position: absolute;
  3.     width: 30px;
  4.     height: 30px;
  5.     transform: translate(-50%, -50%);
  6.     left: 50%;
  7.     top: 50%;
  8.     border-radius: 50px;
  9. }
  10. .g-bubble {
  11.     position: absolute;
  12.     inset: 0;
  13.     border-radius: 50%;
  14.     background: hsl(60, 75%, 40%);
  15. }
复制代码
得到这么一个效果,所有圆形小点,都暂时汇聚在容器的中心:

这里需要简单解释一下:

其次,我们借助 SASS,按照元素的顺序,把它们顺序排列到圆环轨迹之上:
  1. $count: 200;
  2. @for $i from 1 through $count {
  3.     .g-bubble:nth-child(#{$i}) {
  4.         --rotate: calc(#{360 / $count} * #{$i} * 1deg);
  5.         transform:
  6.             rotateZ(var(--rotate))
  7.             translate(135px, 0);
  8.         opacity: 1;
  9.     }
  10. }
复制代码
由于我们设置了 div 小球的个数为 200 个,这样,我们就得到了一圈由 200 个圆形小球形成的圆环:

接下来这一步非常重要,我们设定一个动画:

  • 让每个小球在动画的 75% ~ 100% 阶段做透明度从 1 到 0 的变换,而 0% ~ 75% 的阶段保持透明度为 0
  • 让 200 个 div 依次进行这个动画效果(利用负的 animation-delay,从 -0 到 -4000ms),整体上就能形成逐渐消失的效果
  1. @for $i from 1 through $count {
  2.     .g-bubble:nth-child(#{$i}) {
  3.         --rotate: calc(#{360 / $count} * #{$i} * 1deg);
  4.         --delayTime: calc(4000 * #{$i / $count} * -1ms);
  5.         transform:
  6.             rotateZ(var(--rotate))
  7.             translate(135px, 0);
  8.         opacity: 1;
  9.         animation: showAndHide 4000ms linear var(--delayTime) infinite;
  10.     }
  11. }
  12. @keyframes showAndHide {
  13.     0% {
  14.         opacity: 0;
  15.     }
  16.     75% {
  17.         opacity: 0;
  18.     }
  19.     75.1% {
  20.         opacity: 1;
  21.     }
  22.     100% {
  23.         opacity: 0;
  24.     }
  25. }
复制代码
这样,我们就得到了一个圆形小球气泡围绕圆环渐次消失的效果:

配合上整个圆环,效果就会是这样:

很接近了,但是没有随机的感觉,气泡也没有散开的动画。解决的方案:

  • 所以我们需要让气泡在执行透明度变化的同时,进行一个随机的发散位移
  • 小圆形气泡的大小也可以带上一点随机,同时,在动画过程逐渐缩小
当然,整个动画的基础,还是在容器设置了 滤镜 blur() 和 contrast() 的加持之下的,这样,我们给气泡再补上随机动画散开及缩放的动画:
  1. @for $i from 1 through $count {
  2.     .g-bubble:nth-child(#{$i}) {
  3.         --rotate: calc(#{360 / $count} * #{$i} * 1deg);
  4.         --delayTime: calc(4000 * #{$i / $count} * -1ms);
  5.         --scale: #{0.4 + random(10) / 10};
  6.         --x: #{-100 + random(200)}px;
  7.         --y: #{-100 + random(200)}px;
  8.         transform:
  9.             rotateZ(var(--rotate))
  10.             translate(135px, 0);
  11.         opacity: 1;
  12.         animation: showAndHide 4000ms linear var(--delayTime) infinite;
  13.     }
  14. }
  15. @keyframes showAndHide {
  16.     0% {
  17.         transform:
  18.             rotateZ(var(--rotate))
  19.             translate(135px, 0);
  20.         opacity: 0;
  21.     }
  22.     75% {
  23.         opacity: 0;
  24.     }
  25.     75.1% {
  26.         transform:
  27.             rotateZ(var(--rotate))
  28.             translate(135px, 0)
  29.             scale(var(--scale));
  30.         opacity: 1;
  31.     }
  32.     100% {
  33.         transform:
  34.             rotateZ(var(--rotate))
  35.             translate(calc(135px + var(--x)), var(--y))
  36.             scale(.2);
  37.         opacity: 0;
  38.     }
  39. }
复制代码
只看一圈的气泡圆形,我们能得到了这样的效果:

配合上圆环的效果:

配合上父容器的 filter: hue-rotate() 动画,就能实现颜色的动态变换,得到我们最终想要的效果:

这样,没有了第一版本的违和感,整个效果也显得比较自然。
完整的代码,你可以戳这里:CodePen Demo -- Pure CSS Loading Animation
最后


好了,本文到此结束,希望对你有帮助
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

正序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

拉不拉稀肚拉稀

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表