关于前端:涨姿势了有意思的气泡-Loading-效果

42次阅读

共计 5392 个字符,预计需要花费 14 分钟才能阅读完成。

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

这个的确有点意思,然而这是 CSS 可能实现的?

没错,这个成果中的外围气泡成果,其实借助 CSS 中的滤镜,可能比拟轻松的实现,就是所需的元素可能多点。参考咱们之前的:

  • 应用纯 CSS 实现超酷炫的粘性气泡成果
  • 巧用 CSS 实现酷炫的充电动画

圆弧的实现

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

这里须要用到的技术是:

角向突变 conic-gradient() + mask 以及两个伪元素。图片示意如下:

外围代码如下图:

<div class="g-container">
  <div class="g-circle"></div>
</div>
:root {--headColor: hsl(130, 75%, 75%);
    --endColor: hsl(60, 75%, 40%);
}
.g-container {
    position: relative;
    background: #000;
}
.g-circle {
    position: relative;
    width: 300px;
    height: 300px;
    border-radius: 50%;
    background: conic-gradient(var(--headColor) 0, 
        var(--headColor) 10%,
        hsl(120, 75%, 70%), 
        hsl(110, 75%, 65%), 
        hsl(100, 75%, 60%),
        hsl(90, 75%, 55%), 
        hsl(80, 75%, 50%),
        hsl(70, 75%, 45%),
        var(--endColor) 30%,
        var(--endColor) 35%,
        transparent 35%
    );
    mask: radial-gradient(transparent, transparent 119px, #000 120px, #000 120px, #000 100%);
    
    &::before,
    &::after {
        content: "";
        position: absolute;
        inset: 0;
        width: 30px;
        height: 30px;
        background: var(--headColor);
        top: 0;
        left: 135px;
        border-radius: 50%;
    }
    
    &::after {background: var(--endColor);
        left: unset;
        top: 214px;
        right: 26px;
    }
}

这样,咱们就失去了这样一个图形:

气泡的实现

接下来,咱们来实现尾部气泡向外扩散的成果。

因为这里波及了多个气泡的不同静止动画,多个标签元素必定是少不了了。

因而,接下来咱们要做的事件:

  1. 咱们须要多一组元素,将其相对定位到上述圆环的头部或者尾部
  2. 给每个子元素随机设置多个大小不一的圆,色彩保持一致
  3. 给每个子元素随机设置不同方向的,向外扩散的位移动画
  4. 给每个子元素随机设置负的 animation-delay,造成动画上的先后顺序,并以此造成整个有限循环的气泡扩散动画

这里,因为有许多小气泡的动画,这个数量,我设置成了 100。那必定是不能一个一个手写它们的动画代码,须要借助 SASS/LESS 等预处理器的循环、随机等函数。

外围代码如下:

<div class="g-container">
  <div class="g-circle"></div>
  <ul class="g-bubbles">
    <li class="g-bubble"></li>
    // ... 共 100 个 bubble 元素 
    <li class="g-bubble"></li>
  </ul>
</div>
// 下面圆环的代码,保持一致,上面只补充气泡动画的代码
.g-bubbles {
    position: absolute;
    width: 30px;
    height: 30px;
    border-radius: 50px;
    top: 100px;
    left: 235px;
    background: var(--headColor);
}

.g-bubble {
    position: absolute;
    border-radius: 50%;
    background-color: inherit;
}

@for $i from 1 through 100 {.g-bubble:nth-child(#{$i}) {--rotate: calc(#{random(360)} * 1deg);
        --dis: calc(#{random(100)} * 1px);
        --width: calc(3px + #{random(25)} * 1px);
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        width: var(--width);
        height: var(--width);
        animation: move #{(random(1500) + 1500) / 1000}s ease-in-out -#{random(3000) / 1000}s infinite;
    }
}

@keyframes move {
    0% {transform: translate(-50%, -50%) rotate(0deg);
    }
    75% {opacity: .9;}
    100% {transform: rotateZ(var(--rotate)) translate(-50%, var(--dis));
        opacity: .4;
    }
}

外围在于 @for $i from 1 through 100 {} 这段 SASS 代码外部,咱们实现了下面说的 (2)(3)(4) 的性能点!

这样,咱们就失去了这样一个成果,在尾部有大量气泡动画,一直向外扩散的成果:

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

OK,到这里整个成果根本就做完了。当然,也是剩下最初最重要的一步,须要让多个气泡之间产生一种粘性交融的成果。

这个技巧在此前十分多篇文章中,也频繁提及过,就是利用 filter: contrast() 滤镜与 filter: blur() 滤镜。

如果你还不理解这个技巧,能够戳我的这篇文章看看:你所不晓得的 CSS 滤镜技巧与细节

简述下该技巧:

独自将两个滤镜拿进去,它们的作用别离是:

  1. filter: blur():给图像设置高斯含糊成果。
  2. filter: contrast():调整图像的对比度。

然而,当他们“合体”的时候,产生了微妙的交融景象。

认真看两圆相交的过程,在边与边接触的时候,会产生一种边界交融的成果,通过对比度滤镜把高斯含糊的含糊边缘给干掉,利用高斯含糊实现交融成果。

基于此,咱们再简略革新下咱们的 CSS 代码,所须要加的代码量非常少:

  1. 加上滤镜 blur() 和 contrast(),造成交融粘性成果
  2. 加上整个圆环的旋转即可成果
  3. 加上滤镜 hue-rotate(),实现色调的变换动画
.g-container {
    // ... 保持一致
    background: #000;
    filter: blur(3px) contrast(5);
    animation: rotate 4s infinite linear;
}
@keyframes rotate {
    100% {transform: rotate(360deg);
        filter: blur(3px) contrast(5) hue-rotate(360deg);
    }
}

就这样,咱们就大抵还原了题图的成果:

残缺的代码,你能够戳这里:CodePen Demo — Pure CSS Loading Animation

修复违和感

当然,下面的成果,乍一看还行,认真看,违和感很重。

起因在,扩散出来的小球也跟着一起半圆环一起进行了旋转动画,看上去就有点奇怪。

正确的做法应该是,圆环尾部的气泡应该是原地发散隐没的。

那么,怎么可能做到气泡成果,始终产生在圆环的尾部,同时隐没的时候有不跟着整个圆环一起进行旋转呢?咱们想要的最终成果,应该是这样:

这里,咱们能够拆解一下。设想,如果去掉圆环的旋转,其实咱们只须要实现这样一个成果即可:

整个动画的外围就转变成了如何实现这么一个成果。看似简单,其实也很好做。

首先,咱们从新革新一下上述的 .g-bubbles

  1. 生成 N 个一样大小的小球元素,定位在整个容器的两头
<div class="g-container">
  <div class="g-circle"></div>
  <ul class="g-bubbles">
    <li class="g-bubble"></li>
    // ... 共 200 个 bubble 元素 
    <li class="g-bubble"></li>
  </ul>
</div>
.g-bubbles {
    position: absolute;
    width: 30px;
    height: 30px;
    transform: translate(-50%, -50%);
    left: 50%;
    top: 50%;
    border-radius: 50px;
}
.g-bubble {
    position: absolute;
    inset: 0;
    border-radius: 50%;
    background: hsl(60, 75%, 40%);
}

失去这么一个成果,所以圆形小点,都临时汇聚在容器的核心:

这里须要简略解释一下:

其次,咱们借助 SASS,依照元素的程序,把它们顺序排列到圆环轨迹之上:

$count: 200;
@for $i from 1 through $count {.g-bubble:nth-child(#{$i}) {--rotate: calc(#{360 / $count} * #{$i} * 1deg);
        transform: 
            rotateZ(var(--rotate)) 
            translate(135px, 0);
        opacity: 1;
    }
}

因为咱们设置了 div 小球的个数为 200 个,这样,咱们就失去了一圈由 200 个圆形小球造成的圆环:

接下来这一步十分重要,咱们设定一个动画:

  1. 让每个小球在动画的 75% ~ 100% 阶段做透明度从 1 到 0 的变换,而 0% ~ 75% 的阶段放弃透明度为 0
  2. 让 200 个 div 顺次进行这个动画

顺次隐没:

@for $i from 1 through $count {.g-bubble:nth-child(#{$i}) {--rotate: calc(#{360 / $count} * #{$i} * 1deg);
        --delayTime: calc(4000 * #{$i / $count} * -1ms);
        transform: 
            rotateZ(var(--rotate)) 
            translate(135px, 0);
        opacity: 1;
        animation: showAndHide 4000ms linear var(--delayTime) infinite;
    }
}
@keyframes showAndHide {
    0% {opacity: 0;}
    75% {opacity: 0;}
    75.1% {opacity: 1;}
    100% {opacity: 0;}
}

这样,咱们就失去了一个圆形小球气泡围绕圆环渐次隐没的成果:

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

很靠近了,然而没有随机的感觉,气泡也没有散开的动画。解决的计划:

  1. 所以咱们须要让气泡在执行透明度变动的同时,进行一个随机的发散位移
  2. 小圆形气泡的大小也能够带上一点随机,同时,在动画过程逐步放大

当然,整个动画的根底,还是在容器设置了 滤镜 blur() 和 contrast() 的加持之下的,这样,咱们给气泡再补上随机动画散开及缩放的动画:

@for $i from 1 through $count {.g-bubble:nth-child(#{$i}) {--rotate: calc(#{360 / $count} * #{$i} * 1deg);
        --delayTime: calc(4000 * #{$i / $count} * -1ms);
        --scale: #{0.4 + random(10) / 10};
        --x: #{-100 + random(200)}px;
        --y: #{-100 + random(200)}px;
        transform: 
            rotateZ(var(--rotate)) 
            translate(135px, 0);
        opacity: 1;
        animation: showAndHide 4000ms linear var(--delayTime) infinite;
    }
}

@keyframes showAndHide {
    0% {
        transform: 
            rotateZ(var(--rotate)) 
            translate(135px, 0);
        opacity: 0;
    }
    75% {opacity: 0;}
    75.1% {
        transform: 
            rotateZ(var(--rotate)) 
            translate(135px, 0)
            scale(var(--scale));
        opacity: 1;
    }
    100% {
        transform: 
            rotateZ(var(--rotate)) 
            translate(calc(135px + var(--x)), var(--y))
            scale(.2);
        opacity: 0;
    }
}

只看一圈的气泡圆形,咱们能失去了这样的成果:

配合上圆环的成果:

配合上父容器的 filter: hue-rotate() 动画,就能实现色彩的动静变换,失去咱们最终想要的成果:

这样,没有了第一版本的违和感,整个成果也显得比拟天然。

残缺的代码,你能够戳这里:CodePen Demo — Pure CSS Loading Animation

最初

好了,本文到此结束,心愿对你有帮忙 :)

更多精彩 CSS 技术文章汇总在我的 Github — iCSS,继续更新,欢送点个 star 订阅珍藏。

如果还有什么疑难或者倡议,能够多多交换,原创文章,文笔无限,满腹经纶,文中若有不正之处,万望告知。

正文完
 0