WEB加载动画之三色融合球

1,612 阅读3分钟

这是我参与11月更文挑战的第28天,活动详情查看:2021最后一次更文挑战

介绍

本期我们将用scss+svg去完成一款简单实用的加载动画——三色融合球,顾名思义,我们会做三个颜色的小球,进行变形旋转然后融合到一起最后循环往复这个操作。

我们先来直接看看做好的效果吧:

VID_20211127_210224.gif

正文

1.基础结构

<div id="app">
    <div class="loading">
        <div class="loading-circle"></div>
        <div class="loading-circle"></div>
        <div class="loading-circle"></div>
    </div>
</div>
#app{
    width: 100%;
    height: 100vh;
    background-image: repeating-linear-gradient(90deg, hsla(196,0%,79%,0.06) 0px, hsla(196,0%,79%,0.06) 1px,transparent 1px, transparent 96px),repeating-linear-gradient(0deg, hsla(196,0%,79%,0.06) 0px, hsla(196,0%,79%,0.06) 1px,transparent 1px, transparent 96px),repeating-linear-gradient(0deg, hsla(196,0%,79%,0.09) 0px, hsla(196,0%,79%,0.09) 1px,transparent 1px, transparent 12px),repeating-linear-gradient(90deg, hsla(196,0%,79%,0.09) 0px, hsla(196,0%,79%,0.09) 1px,transparent 1px, transparent 12px),linear-gradient(90deg, rgb(255,255,255),rgb(255,255,255));
    overflow: hidden;
    display: flex;
    justify-content: center;
    align-items: center;
    position: relative;
}
.loading{
    width: 200px;
    height: 200px;
    position: relative;
    .loading-circle{
        width: 60px;
        height: 60px;
        border-radius: 50%;
        position: absolute;
        left: 50%;
        top: 50%;
        margin: -30px 0 0 -30px;
    }
}

结构很简单就是div#app我们将会铺满全屏又用repeating-linear-gradient绘制出了方格背景。然后div.loading做一个正方形性,里面会放三个用绝对定位于中央的小圆形。

2.小球动画

$colors:rgb(255, 208, 0),rgb(139, 203, 255),rgba(252, 96, 96, 0.945);
$duration:2s;

.loading-circle{
    @for $i from 1 through length($colors) { 
            &:nth-child(#{$i}) {
                background-color:nth($colors, $i);
                animation: #{'circle-move-'+$i} $duration infinite;
            }
      }
}

@keyframes circle-move-1 {
    0%,20%,100%{transform: translate(0,0) scale(1)}
    40% {transform: translate(0,-18px) scale(.5)}
    60% {transform: translate(0,-85px) scale(.5)}
    80% {transform: translate(0,-85px) scale(.5)}
}

@keyframes circle-move-2 {
    0%,20%,100%{transform: translate(0,0) scale(1)}
    40% {transform: translate(-16px, 12px) scale(.5)}
    60% {transform: translate(-90px, 65px) scale(.5)}
    80% {transform: translate(-90px, 65px) scale(.5)}
}

@keyframes circle-move-3 {
    0%,20%,100%{transform: translate(0,0) scale(1)}
    40% {transform: translate(16px, 12px) scale(.5)}
    60% {transform: translate(90px, 65px) scale(.5)}
    80% {transform: translate(90px, 65px) scale(.5)}
}

这里就开始说重点了,我们先要用scss定义两个变量,一个是colors表示这三个小球的颜色,用了scss中的list数组。而另一个变量是colors表示这三个小球的颜色,用了scss中的list数组。而另一个变量是duration,它代表这我们一个动画的周期。

接下来,我们通过scss的@for方法进行遍历,去设置这三个小球的颜色和动画,这里注意scss用nth(colors,colors, i)这个方式去获取数组下的值,但是$i的下标与js不同,不能等于0,如果@for从0开始则会就直接会报错。

至于动画,就是让他三个球在某个时间段缩小从中间偏移出去,到了一定程度再回来循环往复,详细的就直接看代码,这里不再过多赘述。

VID_20211127_200947.gif

3.改变顺序

.loading-circle{
    @for $i from 1 through length($colors) { 
            &:nth-child(#{$i}) {
                background-color:nth($colors, $i);
                animation: #{'circle-move-'+$i} $duration infinite,change-z-index #{$duration * length($colors)} -#{$duration * $i} infinite;
            }
      }
}
@keyframes change-z-index{
    0%,100%{ 
        z-index: 3;
    }
    33.33%{
        z-index: 2;
    }
    66.66%{
        z-index: 1;
    }
}

刚才也看到了,我们的三个小球因为是绝对定位,所以每当聚集在一起的时候总是最下面的会遮盖其他小球。上面用的方法就是通过z-index去根据周期设置优先级,然后就可以不停的改变了。

VID_20211127_203951.gif

4.旋转动画

.loading{
    animation: rotate $duration infinite;
}
@keyframes rotate{
    0%,60%{
        transform: rotate(0deg);
    }
    80%,100%{
        transform: rotate(360deg);
    }
}

此时,我们界面还不够炫,还要让他们三个在分开的时候转起来,上面的代码就是每当小球一个周期完成,我们就让他旋转一次,当然这个动画直接加在div.loading上就行,不要粗心的加在小球上。

VID_20211127_215940.gif

5.融合处理

<svg xmlns="http://www.w3.org/2000/svg">
    <defs>
        <filter id="mix">
            <feGaussianBlur in="SourceGraphic" stdDeviation="10" result="blur" />
            <feColorMatrix in="blur" mode="matrix" values="1 0 0 0 0  0 1 0 0 0  0 0 1 0 0  0 0 0 21 -7"/>
        </filter>
    </defs>
</svg>
.loading{
    filter: url(#mix);
}

我们的题目是要怎么让他们融合。很多小伙伴会相信会想到用css的filter的contrast+blur去完成,但是这样不行,会污染我们想要的颜色,所以这里用svg写了一套滤镜,这里说一下,svg的filter元素作用是仅作为滤镜操作的内容,本身没有什么可以呈现的内容。使用也是通过css的filter用url去引入使用。上面的代码就是做了一个模糊识别处理,这段代码可以通用哦。这样,就大功告成了~

VID_20211127_210224.gif

写到这里我们就完成了这整个动画,在线演示

结语

不知道学完这个案例你是否有收获,反正我实现它的时候,感觉scss书写真的太好用,寥寥几句就可以完成很多事,而且非常优雅也便于维护。再就是配合svg的滤镜虽然非常晦涩,但功能真是炒鸡强大,感觉要走的路还有很多,还会有更多的效果等着我们去想象和挖掘。还等什么?一起也来探索一下吧。