使用純 CSS 實現超酷炫的粘性氣泡效果

来源:https://www.cnblogs.com/coco1s/archive/2022/07/05/16445448.html
-Advertisement-
Play Games

最近,在 CodePen 上看到這樣一個非常有意思的效果: 這個效果的核心難點在於氣泡的一種特殊融合效果。 其源代碼在:CodePen Demo -- Goey footer,作者主要使用的是 SVG 濾鏡完成的該效果,感興趣的可以戳源碼看看。 其中,要想靈活運用 SVG 中的 feGaussian ...


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

這個效果的核心難點在於氣泡的一種特殊融合效果。

其源代碼在: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 從底部無規律的進行向上升起的動畫。

這裡,就需要運用我們在 深入淺出 CSS 動畫 這篇文章中所介紹的一種技巧 -- 利用 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);
    }
}

這裡:

  1. 我們利用了 SASS 隨機函數 $width: random(100) + px;,隨機生成不同大小的 div 圓形
  2. 利用 SASS 隨機函數 left: #{(random(100)) + '%'}top: #{(random(100))}px 基於父元素隨機定位
  3. 最為核心的是 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 濾鏡技巧與細節

簡述下該技巧:

單獨將兩個濾鏡拿出來,它們的作用分別是:

  1. filter: blur(): 給圖像設置高斯模糊效果。
  2. 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 是作用於元素背後的區域所覆蓋的所有元素,如果你想瞭解更多關於 backdrop-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

最後

本文與之前的 巧用 CSS 實現酷炫的充電動畫 內使用的技巧非常類似,但本文也有一些新的知識點,大家可以結合著一起看看。

好了,本文到此結束,希望對你有幫助

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 實現APP首頁tabbar滾動吸頂功能 首頁代碼: WillPopScope( child: Scaffold( backgroundColor: Colors.white, appBar: PreferredSize( preferredSize: Size(double.infinity, 0. ...
  • 如何搭建android源代碼repo倉庫 . 版本: v0.3 作者:河東西望 日期:2022-7-5 . 如果你的開發是基於AOSP源碼來建倉,那麼搭建repo伺服器和部署自己的repo倉庫就是非常必要的工作了。 現實中很多公司都是直接把AOSP源代碼放在一個git倉庫中來管理,這樣做沒什麼毛病。 ...
  • 在互聯網世界,驗證用戶身份是一個常見又重要的場景,應用最廣泛的方式當屬帳號密碼驗證。隨著開發者對身份驗證安全性要求不斷提升,加之用戶更加註重過程中的隱私與便捷,身份驗證的方式逐漸多樣化,有動態令牌、簡訊驗證碼、生物特征認證等方式。本文主要從安全性的角度,探討幾種常見身份驗證方式存在的安全漏洞,為開發 ...
  • 本文簡介 點贊 + 關註 + 收藏 = 學會了 ES6 推出的 const 可以定義常量。在 JS 中,常量是不可改變的。這個 “不可改變” 指的是常量存放的記憶體地址不變。 眾所周知,使用 const 定義的常量,如果是基礎類型的數據,值不能變。但如果是引用類型的數據(比如對象、數組等),是可以修改 ...
  • 本文簡介 點贊 + 關註 + 收藏 = 學會了 這是一次真實的 藍牙收發數據 的全過程講解。 本文使用 uni-app + Vue3 的方式進行開發,以手機app的方式運行(微信小程式同樣可行)。 uni-app 提供了 藍牙 和 低功耗藍牙 的 api ,和微信小程式提供的 api 是一樣的,所以 ...
  • 黑夜模式 作為一個前端學習者,自然懂得黑夜模式的重要性,可惜主題原生未提供,那就自己弄吧 個人博客作為效果參考:https://jieniyou.github.io/ 設置基礎樣式 參考其他優秀產品的黑夜模式,得出共性: 那就是黑夜模式的背景一般不會是純黑(#000);而是淡黑色,字體也不是純白(# ...
  • 這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 先從面向對象講起,本瓜認為:面向對象編程,它的最大能力就是:復用! 咱常說,面向對象三大特點,封裝、繼承、多態。 這三個特點,以“繼承”為核心。封裝成類,是為了繼承,繼承之後再各自發展(重寫),可理解為多態。所以,根本目的是為了繼承,即“ ...
  • 這18個網站是我在取經路上意外發現的,裡面包括 純CSS 實現的炫酷背景,還有專門製作背景圖的網站。 算是取經路上的大補之物~ 1. CSS3 Patterns Gallery 🎗️ 傳送門:『CSS3 Patterns Gallery』 如果你認識 Lea Verou 的話,大概率知道這個網站, ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...