【動畫進階】神奇的 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
  • 前言 插件化的需求主要源於對軟體架構靈活性的追求,特別是在開發大型、複雜或需要不斷更新的軟體系統時,插件化可以提高軟體系統的可擴展性、可定製性、隔離性、安全性、可維護性、模塊化、易於升級和更新以及支持第三方開發等方面的能力,從而滿足不斷變化的業務需求和技術挑戰。 一、插件化探索 在WPF中我們想要開 ...
  • 歡迎ReaLTaiizor是一個用戶友好的、以設計為中心的.NET WinForms項目控制項庫,包含廣泛的組件。您可以使用不同的主題選項對項目進行個性化設置,並自定義用戶控制項,以使您的應用程式更加專業。 項目地址:https://github.com/Taiizor/ReaLTaiizor 步驟1: ...
  • EDP是一套集組織架構,許可權框架【功能許可權,操作許可權,數據訪問許可權,WebApi許可權】,自動化日誌,動態Interface,WebApi管理等基礎功能於一體的,基於.net的企業應用開發框架。通過友好的編碼方式實現數據行、列許可權的管控。 ...
  • Channel 是乾什麼的 The System.Threading.Channels namespace provides a set of synchronization data structures for passing data between producers and consume ...
  • efcore如何優雅的實現按年分庫按月分表 介紹 本文ShardinfCore版本 本期主角: ShardingCore 一款ef-core下高性能、輕量級針對分表分庫讀寫分離的解決方案,具有零依賴、零學習成本、零業務代碼入侵適配 距離上次發文.net相關的已經有很久了,期間一直在從事java相關的 ...
  • 前言 Spacesniffer 是一個免費的文件掃描工具,通過使用樹狀圖可視化佈局,可以立即瞭解大文件夾的位置,幫助用戶處理找到這些文件夾 當前系統C盤空間 清理後系統C盤空間 下載 Spacesniffer 下載地址:https://spacesniffer.en.softonic.com/dow ...
  • EDP是一套集組織架構,許可權框架【功能許可權,操作許可權,數據訪問許可權,WebApi許可權】,自動化日誌,動態Interface,WebApi管理等基礎功能於一體的,基於.net的企業應用開發框架。通過友好的編碼方式實現數據行、列許可權的管控。 ...
  • 一、ReZero簡介 ReZero是一款.NET中間件 : 全網唯一開源界面操作就能生成API , 可以集成到任何.NET6+ API項目,無破壞性,也可讓非.NET用戶使用exe文件 免費開源:MIT最寬鬆協議 , 一直從事開源事業十年,一直堅持開源 1.1 純ReZero開發 適合.Net Co ...
  • 一:背景 1. 講故事 停了一個月沒有更新文章了,主要是忙於寫 C#內功修煉系列的PPT,現在基本上接近尾聲,可以回頭繼續更新這段時間分析dump的一些事故報告,有朋友微信上找到我,說他們的系統出現了大量的http超時,程式不響應處理了,讓我幫忙看下怎麼回事,dump也抓到了。 二:WinDbg分析 ...
  • 開始做項目管理了(本人3年java,來到這邊之後真沒想到...),天天開會溝通整理需求,他們講話的時候忙裡偷閑整理一下常用的方法,其實語言還是有共通性的,基本上看到方法名就大概能猜出來用法。出去打水的時候看到外面太陽好好,真想在外面坐著曬太陽,回來的時候好兄弟三年前送給我的鍵盤D鍵不靈了,在打"等待 ...