CSS 還原拉斯維加斯球數字動畫

来源:https://www.cnblogs.com/coco1s/archive/2023/10/18/17771576.html
-Advertisement-
Play Games

我的小冊 《CSS 技術揭秘與實戰通關》上線了,想瞭解更多有趣、進階、系統化的 CSS 內容,可以猛擊 - LINK。 最近大家刷抖音,是否有刷到拉斯維加斯的新地標 「Sphere」: 場館內部的視覺效果非常驚人,其中一個效果讓我虎軀一震: 我的第一想法就是,這個看起來用 CSS 也可以實現嘛?還有 ...


我的小冊 《CSS 技術揭秘與實戰通關》上線了,想瞭解更多有趣、進階、系統化的 CSS 內容,可以猛擊 - LINK

最近大家刷抖音,是否有刷到拉斯維加斯的新地標 「Sphere」:

場館內部的視覺效果非常驚人,其中一個效果讓我虎軀一震:

我的第一想法就是,這個看起來用 CSS 也可以實現嘛?還有 CSS 不能實現的?

本文,就將嘗試使用 CSS,大致還原這個效果。

拆解動畫效果

其實,上述的動畫效果,本質就是一個 3D 立方體。

同時,3D 立方體上每個面存在顏色不一樣的文字,文字和顏色都在隨機變化。

也就是說,我們需要實現一個 3D 立方體:

同時,我們還需要實現這樣一個動畫效果 -- 文字和顏色都在隨機變化的平面效果:

兩者組合一下,再挪動 3D 元素的景深距離,就能實現我們想要的效果!

好,下麵我們一個一個實現。

實現一個 3D 立方體

實現一個 3D 立方體,相對另外一個文字和顏色都在隨機變化的平面效果而言,屬於非常非常簡單的一步了。

我們在非常多篇文章中也講過具體的實現方式:

最常見的 3D 圖形,莫過於一個 3D 立方體。

如果沒有上下兩個面,只是一個 4 個面的圖形,大概是這樣:

這樣一個圖形,利用 CSS 3D,如何快速實現呢?

首先,構造這麼一個結構:

<div class="perspective">
        <div class="container">
                <div class="img">3</div>
                <div class="img">D</div>
                <div class="img">視</div>
                <div class="img">圖</div>
        </div>
</div>

4 個面,就是最內層的 4 個 .img,首先,需要給兩個父容器,設置 3D 的屬性:

.perspective {
  perspective: 3000px;
}
.container {
  width: 400px;
  height: 400px;
  transform-style: preserve-3d;
}

簡單解釋一下:

  1. perspective 可以作用於元素的後代,設置在最上層即可;
  2. transform-style: preserve-3d 設置給最終需要 3D 空間的元素的父容器之上,由於最終是 4 個 .img 需要 3D 空間,因此設置給 .container 即可。

接下來,就是最為核心的,如何設置 4 個 .img 元素的 3D 變換,使之形成 3D 立方體。

技巧就是:先旋轉,再位移

這裡給出一個俯視效果圖:

以上述 Demo 中的正方體為例子,class 為 .img 的 div 塊的高寬為 400px*400px。那麼要利用 4 個 這樣的 div 拼接成一個正方體,需要分別將 4 個 div 繞 Y 軸旋轉 [90°, 180°, 270°, 360°],再 translateY(200px)

值得註意的是,一定是先旋轉角度,再偏移距離,這個順序很重要

代碼如下:

.img {
        position: absolute;
        top: 0;
        left: 0;
        width: 400px;
        height: 400px;
}
@for $i from 1 through $imgCount {
        .img:nth-child(#{$i}) {
                transform: rotateY(($i * 90deg)) translateZ(200px);
        }
}

效果如下:

此時,可能會覺得圖片太太太大了,此時,我們可以通過給中間層 .container 設置一個恰當的 translateZ 進行視覺大小上的調節。

.container {
    transform: translateZ(-3000px);
}

這樣,就能得到恰當大小的立方體元素效果:

完整的代碼,你可以戳這裡:CodePen Demo -- 3D Cube

當然,對於我們這個效果,我們 5 要五個面(前後左右與上方即可),因此,我們基於上述的基礎知識鋪墊,重新實現一個我們需要的框架結構:

<div class="perspective">
  <div class="container">
    <div class="g-panel"></div>
    <div class="g-panel"></div>
    <div class="g-panel"></div>
    <div class="g-panel"></div>
    <div class="g-panel"></div>
  </div>
</div>

並且,我們希望我們的圖形是一個立方體,只需要稍微改造長寬和 translateZ() 的即可。這樣,我們就能得到一個前後左右與上方 5 個面的立方體元素。

示意效果如下:

實現文字動畫效果

OK,立方體我們先放在一邊。

接下來,我們嘗試來實現這個效果:

這個效果如果一個文字用一個 DIV 承載實現,那是非常容易的,但是這樣勢必會造成元素過多,再設置動畫效果,則會導致頁面太為卡頓

所以,我們需要另闢蹊徑。這裡,我們可以使用多層漸變配合 background-clip: text

首先,我們利用等寬字體,隨機實現一列文字:

<div>ABCDEFGHIJKLMN</div>
div {
    font-family: monospace;
    text-align: center;
    font-size: 25px;
    width: 25px;
    line-height: 25px;
    color: #fff;
}

效果大致如下:

此時,如果我們再利用線性漸變,給每個字元的對應空間(也就 25px x 25px),設置上不同的顏色,大概是這樣:

@function randomLinear($count) {
    $value: '';
    
    @for $i from 0 through ($count - 1) {
        $value: $value + randomColor() + string.unquote(" 0 #{$i * 25}px,");
    }
    
    @return linear-gradient(string.unquote(#{$value}) randomColor() 0 100%);
}
@function randomColor() {
    @return rgb(randomNum(255), randomNum(255), randomNum(255));
}
div {
    // ...
    background: randomLinear(14);
}

其中,randomLinear(14) 是一個 SASS 函數,參數 14 表示生成 14 層線性漸變,每一個文字區域的顏色都是隨機的,經過編譯後的其中一種結果如下:

div {
    // ...
    background: linear-gradient(#feea96 0 25px, #edde42 0 50px, #e2344a 0 75px, #cdab7e 0 100px, #e16c8b 0 125px, #dcdc7d 0 150px, #dcb42a 0 175px, #d6a587 0 200px, #984f71 0 225px, #221e34 0 250px, #5e9a69 0 275px, #a955e4 0 300px, #4e908f 0 325px, #8d177e 0 350px);
}

上面,我們按照每間隔 25px 的高度,利用線性漸變隨機設置了一種顏色,最終,能夠得到這麼個效果:

此時,我們只需要再設置 background-clip: text,配合透明文字顏色 color: transparent,就可以實現單個 div 內,單列文字,每個字體的顏色都是不一樣的:

div {
    // ...
    background: randomLinear(14);
    background-clip: text;
    color: transparent;
}

此時,效果如下:

當然,文字顏色可以隨機,那麼文字本身也應該隨機。這個不難,我們也可以藉助 SASS 函數,編寫一個隨機字元的函數,通過元素的偽元素 content 進行設置。

那麼此時,完整的代碼可能是這樣的:

<div></div>
$str: 'QWERTYUIOPASDFGHJKLZXCVBNMabcdefghigklmnopqrstuvwxyz123456789';
$length: str-length($str);

@function randomLinear($count) {
    $value: '';
    
    @for $i from 0 through ($count - 1) {
        $value: $value + randomColor() + string.unquote(" 0 #{$i * 25}px,");
    }
    
    @return linear-gradient(string.unquote(#{$value}) randomColor() 0 100%);
}
@function randomColor() {
    @return rgb(randomNum(255), randomNum(255), randomNum(255));
}
@function randomChar() {
    $r: random($length);
    @return str-slice($str, $r, $r);
}
@function randomChars($number) {
    $value: '';

    @if $number > 0 {
        @for $i from 1 through $number {
            $value: $value + randomChar();
        }
    }
    @return $value;
}

div {
    position: relative;
    width: 25px;
    height: 350px;

    &::before {
        content: randomChars(14);
        position: absolute;
        font-family: monospace;
        background: randomLinear(14);
        background-clip: text;
        color: transparent;
        text-align: center;
        font-size: 25px;
        width: 25px;
        line-height: 25px;
    }
}

這樣,每次 div 內的文字,都是從上面 SASS 函數中 $str 變數中隨機取的:

接下來,我們需要實現文字的隨機跳變,也很好做,我們需要在一開始,隨機生成多個不同的 content,然後,藉助 CSS 動畫,進行切換。

div {
   &::before {
        content: randomChars(14);
        --content1: "#{randomChars(14)}";
        --content2: "#{randomChars(14)}";
        --content3: "#{randomChars(14)}";
        --content4: "#{randomChars(14)}";
        animation: contentChange 1s infinite;
    }
}

@keyframes contentChange {
    20% {
        content: var(--content1);
    }
    40% {
        content: var(--content2);
    }
    60% {
        content: var(--content3);
    }
    80% {
        content: var(--content4);
    }
}

這裡,我們一次生成了 5 個 content,其中 4 個用 CSS 變數保存了起來,隨後,在 CSS 動畫中,利用提前生成好的 content,進行字元內容的替換,此時,整個效果如下:

隨機內容有了,單個字體顏色不一樣有了,就差顏色的隨機跳變動畫了,這個也非常好做,我們在多篇文章也提及過,利用 filter: hue-rotate() 可以快速實現內容的顏色切換。

div {
    animation: colorChange 1s steps(12) infinite;
}
@keyframes colorChange {
    100% {
        filter: hue-rotate(360deg);
    }
}

我們利用了 filter: hue-rotate() 加上了步驟動畫(steps),成功的實現了顏色的跳變!效果如下:

當然,我們最終要實現的是整個面隨機顏色加上隨機文字的跳變動畫,只需要在上述的基礎上,利用 SASS 函數,迴圈重覆多列操作即可。基於上述所有內容的鋪墊,我們最終的單個面下的動畫效果代碼如下:


<div class="g-container">
  <div></div>
  // ... 一個 32 個子 div
  <div></div>
</div>
@use "sass:string";

$str: 'QWERTYUIOPASDFGHJKLZXCVBNMabcdefghigklmnopqrstuvwxyz123456789';
$length: str-length($str);
$size: 25;
$count: 41;

@function randomNum($max, $min: 0, $u: 1) {
    @return ($min + random($max)) * $u;
}

@function randomLinear($count) {
    $value: '';
    
    @for $i from 0 through ($count - 1) {
        $value: $value + randomColor() + string.unquote(" 0 #{$i * 25}px,");
    }
    
    @return linear-gradient(string.unquote(#{$value}) randomColor() 0 100%);
}

@function randomColor() {
    @return rgb(randomNum(255), randomNum(255), randomNum(255));
}

@function randomChar() {
    $r: random($length);
    @return str-slice($str, $r, $r);
}

@function randomChars($number) {
    $value: '';

    @if $number > 0 {
        @for $i from 1 through $number {
            $value: $value + randomChar();
        }
    }
    @return $value;
}

body,
html {
    width: 100%;
    height: 100%;
    background: #000;
    font-family: monospace;
}

.g-container {
    position: relative;
    width: 800px;
    height: 800px;
    display: flex;
    animation: colorChange 1s steps(12) infinite;
    
    div {
        position: relative;
        width: #{$size}px;
        height: 800px;
        flex-shrink: 0;
        
        &::before {
            position: absolute;
            inset: 0;
            text-align: center;
            font-size: #{$size}px;
            width: #{$size}px;
            text-align: center;
            line-height: #{$size}px;
            color: transparent;
        }
    }
    
    @for $i from 1 to $count {
        div:nth-child(#{$i}) {
            &::before {
                content: randomChars(32);
                --content1: "#{randomChars(32)}";
                --content2: "#{randomChars(32)}";
                --content3: "#{randomChars(32)}";
                --content4: "#{randomChars(32)}";
                animation: contentChange 1s infinite;
                background: randomLinear(32);
                background-clip: text;
            }
        }
    }
}
@keyframes colorChange {
    100% {
        filter: hue-rotate(360deg);
    }
}
@keyframes contentChange {
    20% {
        content: var(--content1);
    }
    40% {
        content: var(--content2);
    }
    60% {
        content: var(--content3);
    }
    80% {
        content: var(--content4);
    }
}

這樣,我們就成功的實現了單個平面下的,顏色隨機,文字隨機,且不斷變化的動畫效果:

單個平面下的完整代碼,你可以戳這裡:CodePen Demo -- Single Panel Random Text

實現立體效果

有了上面的立方體和單個平面的效果,要實現立體效果就不難了。我們嘗試將兩者結合起來。

改造原有的立方體結構,大致改成如下形式:

.perspective
    .container
        .g-panel
            -for(var i=0; i<32; i++)
                div
        .g-panel
            -for(var i=0; i<32; i++)
                div
        .g-panel
            -for(var i=0; i<32; i++)
                div
        .g-panel
            -for(var i=0; i<32; i++)
                div
        .g-panel
            -for(var i=0; i<32; i++)
                div

上面採用了 PUG 模板引擎來簡化代碼,編譯後的效果如下:

<div class="perspective">
  <div class="container">
    <div class="g-panel">
      <div></div>
      // ... 32 個
      <div></div>
    <div class="g-panel">
      <div></div>
      // ... 32 個
      <div></div>
    <div class="g-panel">
      <div></div>
      // ... 32 個
      <div></div>
    <div class="g-panel">
      <div></div>
      // ... 32 個
      <div></div>
    <div class="g-panel">
      <div></div>
      // ... 32 個
      <div></div>
  </div>
</div>

這裡,我們只需要實現 5 個面的立方體即可(前後左右以及上方)。

每個 .g-panel,實現一個我們上面鋪墊的單面文字跳變效果,這樣,我們就能得到這麼一個立體的 3D 立方體動畫效果:

接下來,我們只需要稍加調試,通過控制 perspectivetransform: translateZ() 控制視覺上的縱深,將畫面的視角放置於整個立方體之中,即可得到這麼個效果:

好,最後,我們模擬文章開頭拉斯維加斯球的效果,讓頂部的平面,向下運動,實現一種天花板往下掉的動畫效果,最終,我們即可使用純 CSS,大致模擬出整個效果:

由於 GIF 錄製問題,實際效果會比 GIF 展示效果更為震撼。

使用 CSS 實現的完整的代碼以及整個效果,你可以點擊這裡進行查看:CodePen Demo -- Las Vegas Sphere Cube Random Text

最後

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

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

-Advertisement-
Play Games
更多相關文章
  • 下載jdk-8u361-linux-x64.tar.gz https://www.oracle.com/java/technologies/downloads 上傳jdk-8u361-linux-x64.tar.gz 到node1 以下命令都是在node1上執行 解壓 tar -zxvf jdk-8 ...
  • 2023金融業資料庫技術大會上,華為雲資料庫服務產品部總經理蘇光牛、華為雲資料庫服務產品部CTO莊乾鋒受邀出席,分享了關於華為雲GaussDB資料庫的設計思考和關鍵技術能力。 ...
  • 在上篇文章中,我們向大家解釋了為什麼實時湖倉是當前企業數字化轉型過程中的解決之道,介紹了實時計算和數據湖結合的應用場景。(“數據驅動”時代,企業為什麼需要實時湖倉?) 在這篇文章中,我們將詳細介紹在數棧實時開發平臺內,實時湖倉的功能架構設計和具體實操案例。 功能架構介紹 實時湖倉並不是一個獨立的產品 ...
  • 使用Base克隆集群節點 先把Base關機,然後右鍵 - 管理 - 克隆 選擇完整克隆 克隆名字這裡叫node1 重覆步驟,克隆node2/node3 為了分類,創建了一個大數據集群文件夾 以下命令全是root許可權執行 配置固定IP # 修改主機名 hostnamectl set-hostname ...
  • mtools是一個基於Python實現的MongoDB工具集,旨在提供一系列功能,包括MongoDB日誌分析、報表生成以及簡易的資料庫安裝等。它由MongoDB原生的工程師單獨發起併進行開源維護。mtools包含了一些常用的組件,如mlaunch、mlogfilter、mplotqueries和ml... ...
  • 一、環境介紹 本文環境,以及本文所採用資料庫為GreatSQL 8.0.32-24 $ cat /etc/system-release Red Hat Enterprise Linux Server release 7.9 (Maipo) $ uname -a Linux gip 3.10.0-11 ...
  • 下載VM與Centos鏡像 用的 VM 17 版本: 該版本解決了老版本的一些藍屏問題和相容性問題 https://download3.vmware.com/software/WKST-1700-WIN/VMware-workstation-full-17.0.0-20800274.exe # 密鑰 ...
  • 接上一節:從零用VitePress搭建博客教程(2) –VitePress預設首頁和頭部導航、左側導航配置 五、預設主題相關細節配置 關於預設主題的標題,logo、頁腳,最後更新時間等相關細節配置,我們也是通過文件config.js中的themeConfig選項配置的,以下所有配置都是在themeC ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...