首頁  >  文章  >  web前端  >  CSS3動畫實戰之:超酷炫的黏性氣泡效果

CSS3動畫實戰之:超酷炫的黏性氣泡效果

青灯夜游
青灯夜游轉載
2022-07-07 10:14:242644瀏覽

這篇文章帶大家聊聊CSS3動畫,看看怎麼使用純 CSS 實現超酷炫的黏性氣泡效果,希望對大家有幫助!

CSS3動畫實戰之:超酷炫的黏性氣泡效果

最近,在CodePen 上看到這樣一個非常有趣的效果:

這個效果的核心困難在於氣泡的一種特殊融合效果。 【推薦學習:css影片教學

其原始碼在:CodePen Demo -- Goey footer,作者主要使用的是 SVG 濾鏡完成的該效果,有興趣的可以戳源碼看看。

其中,要靈活運用 SVG 中的 feGaussianBlur 濾鏡還是需要有非常強大的 SVG 知識儲備的。那麼,僅僅使用 CSS 能否實現該效果呢?

嘿嘿,強大的 CSS 當然是可以的。本文,就將帶領大家一步一步使用純 CSS,完成上述效果。

借助SASS 完成大致效果

首先,如果上述效果沒有氣泡的融合效果,可能就只是這樣:

要製作這樣一個效果還是比較簡單的,只是程式碼會比較多,我們借助SASS 預處理器即可。

假設我們有以下HTML 結構:

<div class="g-wrap">
  <div class="g-footer">
    <div class="g-bubble"></div>
    <div class="g-bubble"></div>
    // ... 200 个 g-bubble
  </div>
</div>

核心要做的,僅僅是讓200 個.g-bubble 從底部無規律的進行向上升起的動畫。

這裡,就需要運用一種技巧 -- 利用 animation-duration 和 animation-delay 來建構隨機效果

#利用animation-duration 和animation-delay 建立隨機效果

同一個動畫,我們利用一定範圍內隨機的animation-duration 和在一定範圍內隨機的animation-delay,可以有效的建構更為隨機的動畫效果,讓動畫更加的自然。

我們來模擬一下,如果是使用10 個animation-durationanimation-delay 都一致的圓的話,核心偽代碼:

<ul>
    <li></li>
    <!--共 10 个...--> 
    <li></li>
</ul>
ul {
    display: flex;
    flex-wrap: nowrap;
    gap: 5px;
}
li {
    background: #000;
    animation: move 3s infinite 1s linear;
}
@keyframes move {
    0% {
        transform: translate(0, 0);
    }
    100% {
        transform: translate(0, -100px);
    }
}

這樣,小球的運動會是這樣的整齊劃一:

#要讓小球的運動顯得非常的隨機,只需要讓animation-durationanimation-delay 都在一定範圍內浮動即可,改造下CSS:

@for $i from 1 to 11 {
    li:nth-child(#{$i}) {
        animation-duration: #{random(2000)/1000 + 2}s;
        animation-delay: #{random(1000)/1000 + 1}s;
    }
}

我們利用SASS 的循環和random() 函數,讓animation-duration 在2-4 秒範圍內隨機,讓animation-delay 在1-2 秒範圍內隨機,這樣,我們就可以得到非常自然且不同的上升動畫效果,基本上不會出現重複的畫面,很好的模擬了隨機效果:

CodePen Demo -- 利用範圍隨機animation-duration 和animation-delay 實現隨機動畫效果

好,我們把上述介紹的技巧,套用到我們本文要實現的效果中去,HTML 結構再看一眼:

<div class="g-wrap">
  <div class="g-footer">
    <div class="g-bubble"></div>
    <div class="g-bubble"></div>
    // ... 200 个 g-bubble
  </div>
</div>

核心的CSS 程式碼:

.g-footer {
    position: absolute;
    bottom: 0;
    left: 0;
    height: 86px;
    width: 100%;
    background: #26b4f5;
}

@for $i from 0 through 200 { 
    .g-bubble:nth-child(#{$i}) {
        position: absolute;
        background: #26b4f5;
        $width: random(100) + px;
        left: #{(random(100)) + '%'};
        top: #{(random(100))}px;
        width: $width;
        height: $width;
        animation: moveToTop #{(random(2500) + 1500) / 1000}s ease-in-out -#{random(5000)/1000}s infinite;
    }
}
@keyframes moveToTop {
    90% {
        opacity: 1;
    }
    100% {
        opacity: .08;
        transform: translate(-50%, -180px) scale(.3);
    }
}

這裡:

  • 我們利用了SASS 隨機函數$width: random(100) px;,隨機產生不同大小的div 圓形

  • 利用SASS 隨機函數left: #{(random(100)) '%'}# ,top: #{(random(100))}px 基於父元素隨機定位

  • 最為核心的是animation: moveToTop #{(random (2500) 1500) / 1000}s ease-in-out -#{random(5000)/1000}s infinite,讓所有div 圓的運動都是隨機的

上述(1)、(2)綜合結果,會產生這樣一種佈局,均勻分散排布的圓形:

注:这里为了方便理解,我隐藏了最外层 g-footer 的颜色,并且给 g-bubble 添加了黑色边框

接着,如果我们替换一下 animation 语句,使用统一的动画时长,去掉负的延迟,变成 animation: moveToTop 4s ease-in-out infinite,动画就会是这样:

整体是整齐划一,没有杂乱无章的感觉的。

运用上随机效果,animation: moveToTop #{(random(2500) + 1500) / 1000}s ease-in-out -#{random(5000)/1000}s infinite,就能得到上述的,不同气泡随机上升的感觉:

添加融合效果

接下来,也是最重要的一步,如何让气泡与气泡之间,以及气泡和底部 .g-footer 之间产生融合效果呢?

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

如果你还不了解这个技巧,可以戳我的这篇文章看看:你所不知道的 CSS 滤镜技巧与细节

简述下该技巧:

单独将两个滤镜拿出来,它们的作用分别是:

  • filter: blur(): 给图像设置高斯模糊效果。

  • filter: contrast(): 调整图像的对比度。

但是,当他们“合体”的时候,产生了奇妙的融合现象。

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

基于此,我们再简单改造下我们的 CSS 代码,所需要加的代码量非常少:

.g-wrap {
    background: #fff;
    filter: contrast(8);
}
.g-footer {
    // ... 其他保持一致
    filter: blur(5px);
}

就这么简单,父容器添加白色底色以及对比度滤镜 filter: contrast(8),子容器添加 filter: blur(5px) 即可,这样,我们就能得气泡的融合效果,基本得到我们想要的效果:

利用 backdrop-filter 替代 filter 消除边缘

但是!利用 filter: blur() 会有一个小问题。

运用了 filter: blur() 的元素,元素边缘的模糊度不够,会导致效果在边缘失真,我们仔细看看动画的边缘:

如何解决呢?也好办,在这里,我们尝试利用 backdrop-filter 去替换 filter

两者之间的差异在于,filter 是作用于元素本身,而 backdrop-filter 是作用于元素背后的区域所覆盖的所有元素。

简单改造下代码,原代码:

.g-footer {
    // ... 
    filter: blur(5px);
}

改造后的代码:

.g-footer {
    // ... 去掉 filter: blur(5px)
    &:before {
        content: "";
        position: absolute;
        top: -300px;
        left: 0;
        right: 0;
        bottom: 0;
        z-index: 1;
        backdrop-filter: blur(5px);
    }
}

我们通过去到原来添加在 .g-footer 上的 filter: blur(5px),通过他的伪元素,叠加一层新的元素在它本身之上,并且添加了替代的 backdrop-filter: blur(5px)

当然,因为这里的 blur(5px) 还需要为气泡与气泡之间的融合服务,所以为了覆盖动画全区域,我们还设置了 top: -300px,扩大了它的作用范围。

最终,我们就能完美的复刻文章一开头,使用 SVG 滤镜实现的效果:

在文章中,我省去了大部分基础的 CSS 代码,完整的代码,你可以戳这里:CodePen Demo -- Bubble Rises

(学习视频分享:web前端入门

以上是CSS3動畫實戰之:超酷炫的黏性氣泡效果的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:segmentfault.com。如有侵權,請聯絡admin@php.cn刪除