【動畫進階】神奇的 3D 卡片反光閃爍動效

来源:https://www.cnblogs.com/coco1s/p/17979602
-Advertisement-
Play Games

最近,有群里在群里發了這麼一個非常有意思的卡片 Hover 動效,來源於此網站 -- key-drop,效果如下: 非常有意思酷炫的效果。而本文,我們不會完全還原此效果,而是基於此效果,嘗試去製作這麼一個類似的卡片交互效果: 該效果的幾個核心點: 卡片的 3D 旋轉跟隨滑鼠移動效果 如何讓卡片在 H ...


最近,有群里在群里發了這麼一個非常有意思的卡片 Hover 動效,來源於此網站 -- key-drop,效果如下:

非常有意思酷炫的效果。而本文,我們不會完全還原此效果,而是基於此效果,嘗試去製作這麼一個類似的卡片交互效果:

該效果的幾個核心點:

  1. 卡片的 3D 旋轉跟隨滑鼠移動效果
  2. 如何讓卡片在 Hover 狀態,有不同的光澤變化
  3. 如何讓卡片在 Hover 狀態,有 Blink,Blink 的星星閃爍效果

當然,要做到卡片的 3D 旋轉跟隨滑鼠移動效果需要一定程度的藉助 JavaScript,因此,最終的效果是 CSS 配合 JavaScript 以及一些動態效果的 Gif 共同實現。

好,下麵就讓我們一步一步一起來實現這個效果。

卡片的 3D 旋轉跟隨效果

OK,接下來,如何實現 3D 卡片效果呢?

這個效果之前在 讓交互更加生動!有意思的滑鼠跟隨 3D 旋轉動效 實現過一次,我們複習一下。

這個交互效果主要有兩個核心:

  1. 藉助了 CSS 3D 的能力
  2. 元素的旋轉需要和滑鼠的移動相結合

我們的目標是實現這樣一個動畫效果:

這裡,我們其實有兩個核心元素:

  1. 滑鼠活動區域
  2. 旋轉物體本身

滑鼠在滑鼠活動區域內的移動,會影響旋轉物體本身的 3D 旋轉,而旋轉的方向其實可以被分解為 X 軸方向與 Y 軸方向。

我們來看一下,假設我們的 HTML 結構如下:

<body>
    <div id="element"></div>
</body>

得到這樣一個圖形:

這裡,body 的範圍就是整個滑鼠可活動區域,也是我們添加滑鼠的 mousemove 事件的宿主 target,而 #element 就是需要跟隨滑鼠一起轉動的旋轉物體本身。

因為整個效果是需要基於 CSS 3D 的,我們首先加上簡單的 CSS 3D 效果:

body {
    width: 100vw;
    height: 100vh;
    transform-style: preserve-3d;
    perspective: 500px;
}

div {
    width: 200px;
    height: 200px;
    background: #000;
    transform-style: preserve-3d;
}

效果如下:

沒有什麼不一樣。這是因為還沒有添加任何的 3D 變換,我們給元素添加 X、Y 兩個方向的 rotate() 試一下(註意,這裡預設的旋轉圓心即是元素中心):

div {
     transform: rotateX(15deg) rotateY(30deg);
}

效果如下,是有那麼點意思了:

好,接下來,我們的目標就是通過結合 mouseover 事件,讓元素動起來。

控制 X 方向的移動

當然,為了更加容易理解,我們把動畫拆分為 X、Y 兩個方向上的移動。首先看 X 方向上的移動:

這裡,我們需要以元素的中心為界:

  1. 當滑鼠在中心右側連續移動,元素繞 Y 軸移動,並且值從 0 開始,越來越大,範圍為(0, +∞)deg
  2. 反之,當滑鼠在中心左側連續移動,元素繞 Y 軸移動,並且值從 0 開始,越來越小,範圍為(-∞, 0)deg

這樣,我們可以得到這樣一個公式:

rotateY = (滑鼠 x 坐標 - 元素左上角 x 坐標 - 元素寬度的一半)deg

通過綁定 onmousemove 事件,我們嘗試一下:

const mouseOverContainer = document.getElementsByTagName("body")[0];
const element = document.getElementById("element");

mouseOverContainer.onmousemove = function(e) {
  let box = element.getBoundingClientRect();
  let calcY = e.clientX - box.x - (box.width / 2);
    
  element.style.transform  = "rotateY(" + calcY + "deg) ";
}

效果如下:

好吧,旋轉的太誇張了,因此,我們需要加一個倍數進行控制:

const multiple = 20;
const mouseOverContainer = document.getElementsByTagName("body")[0];
const element = document.getElementById("element");

mouseOverContainer.onmousemove = function(e) {
  let box = element.getBoundingClientRect();
  let calcY = (e.clientX - box.x - (box.width / 2)) / multiple;
    
  element.style.transform  = "rotateY(" + calcY + "deg) ";
}

通過一個倍數約束後,效果好了不少:

控制 Y 方向的移動

同理,我們利用上述的方式,同樣可以控制 Y 方向上的移動:

const multiple = 20;
const mouseOverContainer = document.getElementsByTagName("body")[0];
const element = document.getElementById("element");

mouseOverContainer.onmousemove = function(e) {
  let box = element.getBoundingClientRect();
  let calcX = (e.clientY - box.y - (box.height / 2)) / multiple;
    
  element.style.transform  = "rotateX(" + calcX + "deg) ";
};

效果如下:

當然,在這裡,我們會發現方向是元素運動的方向是反的,所以需要做一下取反處理,修改下 calcX 的值,乘以一個 -1 即可:

let calcX = (e.clientY - box.y - (box.height / 2)) / multiple * -1;

結合 X、Y 方向的移動

OK,到這裡,我們只需要把上述的結果合併一下即可,同時,上面我們使用的是 onmousemove 觸發每一次動畫移動。現代 Web 動畫中,我們更傾向於使用 requestAnimationFrame 去優化我們的動畫,確保每一幀渲染一次動畫即可。

完整的改造後的代碼如下:

const multiple = 20;
const mouseOverContainer = document.getElementsByTagName("body")[0];
const element = document.getElementById("element");

function transformElement(x, y) {
  let box = element.getBoundingClientRect();
  let calcX = -(y - box.y - (box.height / 2)) / multiple;
  let calcY = (x - box.x - (box.width / 2)) / multiple;
  
  element.style.transform  = "rotateX("+ calcX +"deg) "
                        + "rotateY("+ calcY +"deg)";
}

mouseOverContainer.addEventListener('mousemove', (e) => {
  window.requestAnimationFrame(function(){
    transformElement(e.clientX, e.clientY);
  });
});

至此,我們就能簡單的實現滑鼠跟隨 3D 旋轉動效:

設置平滑出入

現在,還有最後一個問題,就是當我們的滑鼠離開活動區域時,元素的 transform 將停留在最後一幀,正確的表現應該是複原到原狀。因此,我們還需要添加一些事件監聽做到元素的平滑複位。

通過一個 mouseleave 事件配合元素的 transition 即可。

div {
    // 與上述保持一致...
    transition: all .2s;
}
mouseOverContainer.addEventListener('mouseleave', (e) => {
  window.requestAnimationFrame(function(){
    element.style.transform = "rotateX(0) rotateY(0)";
  });
});

至此,我們就可以完美的實現平滑出入,整體效果最終如下:

完整的代碼,你可以戳這裡:CodePen Demo -- CSS 3D Rotate With Mouse Move

Hover 狀態下的光澤變化

好,有了上述鋪墊之後,我們就可以將黑色背景圖,替換成實際的圖片,得到這麼一個初步效果:

接下來,我們需要讓卡片能夠變得有光澤,並且也能基於滑鼠 Hover 的坐標不同,展現出不一樣的效果,像是這樣:

怎麼實現呢?看似複雜,其實只需要簡單的利用混合模式即可。其中本質就是圖片疊加上黑白相間的漸變,再調整混合模式,就能實現上述的高光效果。

代碼如下:

<div></div>
div {
    position: relative;
    background: url('image.png');
    
    &::before {
        content: "";
        position: absolute;
        inset: 0;
        background: 
            linear-gradient(
                115deg, 
                transparent 0%, 
                rgba(255, 255, 255, 0.5 30%), 
                rgba(0, 0, 0, .5) 55%), 
                rgba(255, 255, 255, .5) 80%), 
                transparent 100%
            );
        mix-blend-mode: color-dodge;
    }
}

這裡,我們利用 div 元素的背景展示了圖片,利用元素的偽元素展示了黑白漸變效果,最終再疊加上混合模式 mix-blend-mode: color-dodge,示意圖如下:

但是,此時,只有卡片是有 3D 效果的,疊加的黑白漸變層是不會隨著 Hover 效果進行變化的:

為瞭解決這個問題,我們需要讓漸變圖層也能受到 Hover 的動態影響,這個好做,我們額外引入一個 CSS 變數,基於滑鼠當前 Hover 卡片時,距離卡片最左側的橫向距離,設置動態的 CSS 變數。

改造一下代碼:

<div id="g-img"></div>
div {
    --per: 30%;
    position: relative;
     // ...
    
    &::before {
        content: "";
        position: absolute;
        inset: 0;
        background: 
            linear-gradient(
                115deg, 
                transparent 0%, 
                rgba(255, 255, 255, 0.5) var(--per), 
                rgba(0, 0, 0, .5) calc(var(--per) + 25%), 
                rgba(255, 255, 255, .5) calc(var(--per) + 50%), 
                transparent 100%
            );
        mix-blend-mode: color-dodge;
    }
}
const multiple = 15;
const mouseOverContainer = document.getElementsByTagName("body")[0];
const element = document.getElementById("element");
const img = document.getElementById("g-img");

function transformElement(x, y) {
    let box = element.getBoundingClientRect();
    const calcX = -(y - box.y - box.height / 2) / multiple;
    const calcY = (x - box.x - box.width / 2) / multiple;
    const percentage = parseInt((x - box.x) / box.width * 1000) / 10;
    
    element.style.transform = "rotateX(" + calcX + "deg) " + "rotateY(" + calcY + "deg)";

    // 額外增加一個控制 --per 的變數寫入
    img.style = `--per: ${percentage}%`;
}

mouseOverContainer.addEventListener("mousemove", (e) => {
    window.requestAnimationFrame(function () {
        transformElement(e.clientX, e.clientY);
    });
});

簡單解釋一下,上述代碼最核心的部分就是引入了 --per CSS 變數,其應用在漸變代碼中。

我們通過計算當前滑鼠距離卡片左側的橫向距離,除以卡片整體的寬度,得到 --per 實際表示的百分比,再賦值給 --per,以此實現 Hover 時候的光效變化:

疊加星星閃爍效果

好,效果已經非常接近了。當然,總感覺缺少什麼,我們可以在這一步,繼續疊加上另外一層星星閃爍的效果。

這裡,我們可以用現成的 GIF 圖,像是這樣(圖片來源於 Pokemon Card Holo Effect):

這樣,我們的整個效果,其實就變成了這種疊加狀態:

我們再簡單改造一下代碼:

#g-img {
    --per: 30%;
    position: relative;
    background: url('image.png');
    
    &::after {
        content: "";
        display: none;
        position: absolute;
        inset: 0;
        background: url("https://s3-us-west-2.amazonaws.com/s.cdpn.io/13471/sparkles.gif");
        mix-blend-mode: color-dodge;
    }
    
    &::before {
        content: "";
        display: none;
        position: absolute;
        background: 
            linear-gradient(
                115deg, 
                transparent 0%, 
                rgba(255, 255, 255, 0.7) var(--per), 
                rgba(0, 0, 0, .6) calc(var(--per) + 25%), 
                rgba(255, 255, 255, .5) calc(var(--per) + 50%), 
                transparent 100%
            );
        mix-blend-mode: color-dodge;
    }
    
    &:hover::after,
    &:hover::before {
        display: block;
    }
}

當 Hover 狀態下,才展示漸變背景與星星 Gif 圖的疊加效果,最終,我們就實現了最開頭的效果:

完整的代碼,你可以戳這裡 CodePen Demo -- CSS 3D Rotate With Mouse Move

嘗試不同漸變背景與不同混合模式

瞭解上述製作方式的全過程後,我們就可以改變疊加的混合模式與漸變背景,以創造更多不一樣的效果。

像是這樣:

完整的代碼,你可以戳這裡 CodePen Demo -- CSS 3D Rotate With Mouse Move2

或者是這樣:

完整的代碼,你可以戳這裡 CodePen Demo -- CSS 3D Rotate With Mouse Move3

最後

怎樣,學會了嗎。通過不同的混合模式與不同的漸變背景,可以排列組合出非常多種有趣有意思的效果。感興趣的,一定動手試試!

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

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

-Advertisement-
Play Games
更多相關文章
  • C# 布爾值 在編程中,通常需要一個只能有兩個值之一的數據類型,比如: 是 / 否 開 / 關 真 / 假 為此,C# 有一個 bool 數據類型,可以取 true 或 false 的值。 布爾值 使用 bool 關鍵字聲明布爾類型,只能取 true 或 false 的值: 示例: bool isC ...
  • 概述:在C#中,字元串連接有兩種實現方法:使用`+`運算符和使用`StringBuilder`。前者在每次連接時都會創建新的字元串對象,效率較低。後者通過內部管理字元數組,避免了頻繁的記憶體分配和垃圾回收,因此性能更高。在處理大量字元串連接時,使用`StringBuilder`可以顯著提高性能。這兩種 ...
  • DevToys —— 號稱是開發人員的“瑞士軍刀”,一款適用於開發者的工具集合,包含各種實用的開發小工具。JSON格式化、文本對比、正則表達式...無需網路,離線即可使用! ...
  • Linux 是一個嚴謹的操作系統,每個目錄存放什麼文件是有明確的要求和規範的。我們應該去瞭解這些目錄的作用,然後按照目錄要求去操作。 ...
  • 一、海豚調度介紹 Apache DolphinScheduler 是一個分散式易擴展的可視化DAG工作流任務調度開源系統。適用於企業級場景,提供了一個可視化操作任務、工作流和全生命周期數據處理過程的解決方案。 Apache DolphinScheduler 旨在解決複雜的大數據任務依賴關係,併為應用 ...
  • 下麵介紹三種用於進行排序的專用視窗函數: 1、RANK() 在計算排序時,若存在相同位次,會跳過之後的位次。 例如,有3條排在第1位時,排序為:1,1,1,4······ 2、DENSE_RANK() 這就是題目中所用到的函數,在計算排序時,若存在相同位次,不會跳過之後的位次。 例如,有3條排在第1 ...
  • 在近日舉辦的鴻蒙生態千帆啟航儀式上,華為常務董事、終端BG CEO餘承東表示,鴻蒙生態設備已經增至8億 ,將打開萬億產業新藍海。 在本次論壇上,華為宣佈HarmonyOS NEXT鴻蒙星河版(開發者預覽版)已面向開發者開放申請。該版本,能夠實現原生精緻、原生易用、原生流暢、原生安全、原生智能、原生互 ...
  • 這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 依賴管理解決了在軟體開發過程中管理和協調各種依賴項的問題,簡化了開發流程,提高了項目的可靠性、可維護性和可重覆性。它們幫助開發人員更高效地管理項目的依賴關係,減少了潛在的錯誤和衝突,並提供了更好的開發體驗。 常用的依賴管理 在 JavaS ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...