如圖所示,這是一個很炫酷的鼠標懸停動畫效果,卡片的文字隨着鼠標的移動不斷變化着,且文字的顏色伴隨着漸變色跟隨鼠標移動,中心部分是突出的LOGO效果,整個交互效果十分引人注目。原效果來源於 evervault.com/customers 這個網站,有興趣的可以體驗看看~
本次文章將解析如何用代碼實現這個效果,根據上面的動圖分析出我們要實現的幾個主要功能點:
- 卡片在鼠標懸停時出現漸變隨機文字
- 中心LOGO部分呈透明圓形覆蓋在文字上方
- 漸變文字隨着鼠標的移動隨機變化
- 隨機的文字呈漸變色
代碼實現
界面佈局
根據上面的分析中心的LOGO部分的層級高於文字內容,所以我們的佈局採用定位的方式,使LOGO部分的z-index更高即可,核心代碼如下,card-image即是LOGO部分,card-gradient則是漸變顏色的控制,card-letters控制隨機文本:
html:
<div class="card">
<div class="card-image">
<img src="https://assets.codepen.io/1468070/Hyperplexed+Logo+-+Color+5.svg" />
</div>
<div class="card-gradient"></div>
<div class="card-letters"></div>
</div>
css:
.card {
display: flex;
align-items: center;
justify-content: center;
position: relative;
}
.card-image {
position: relative;
z-index: 4;
}
.card-letters {
position: absolute;
left: 0px;
top: 0px;
height: 100%;
width: 100%;
}
.card-gradient {
height: 100%;
width: 100%;
position: absolute;
z-index: 3;
}
隨機文本效果
這裏的隨機文本需要藉助於JavaScript生成隨機文本再填充到card-letters中,首先定義需要隨機的所有文本字符:
const chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
然後定義隨機字符的函數,這段代碼定義了兩個函數:randomChar 和 randomString。
randomChar 函數通過從 chars 數組中隨機選擇一個字符來生成一個隨機字符。它使用 Math.random() 函數生成一個隨機數,這個隨機數用來在 chars 數組中選取一個隨機的字符。
randomString 函數則生成一個指定長度的隨機字符串。這個函數首先創建一個與給定長度相同的數組,然後用 map 方法對數組中的每個元素調用 randomChar 函數,最後使用 join 方法將所有字符連接成一個字符串。
使用方式只需要調用randomString(length)傳入需要隨機字符的長度即可。
const randomChar = () => chars[Math.floor(Math.random() * (chars.length - 1))],
randomString = length => Array.from(Array(length)).map(randomChar).join("");
當鼠標移動的時候通過監聽onmousemove事件將生成的隨機內容設置到文本標籤的innerText即可。
const handleOnMove = e => {
letters.innerText = randomString(1500);
}
card.onmousemove = e => handleOnMove(e);
以下是設置完成的效果:
卡片內默認文本是不展示的,鼠標移入後展示,離開後消失,這塊採用透明度實現。我們對.card-letters增加透明度的控制,默認透明度是0,鼠標移入修改為1,代碼如下:
.card-letters {
opacity: 0;
transition: opacity 400ms;
}
.card:hover .card-letters {
opacity: 1;
}
移動陰影效果
觀察文章開始的效果可以發現卡片內文本只有在鼠標周圍才是高亮狀態,其他位置都有陰影效果,以此來突出鼠標移動的焦點效果。即然是跟隨鼠標位置而變化,所以我們首先需要獲取到當前鼠標的x,y座標數據。還是基於剛剛的onmousemove事件,稍加改造即可獲取:
const handleOnMove = e => {
+ const rect = card.getBoundingClientRect(),
+ x = e.clientX - rect.left,
+ y = e.clientY - rect.top;
+ letters.style.setProperty("--x", `${x}px`);
+ letters.style.setProperty("--y", `${y}px`);
letters.innerText = randomString(1500);
}
將計算好的x,y通過屬性設置在letters標籤上,下一步我們就可以在CSS使用動態的座標值。
這裏的動態陰影效果我們使用mask-image實現,這裏的陰影本質也是就是漸變背景,通過radial-gradient創意一個從中心向外逐漸變化的效果,代碼如下:
-webkit-mask-image: radial-gradient(
calc(var(--card-size) * 0.8) circle at var(--x) var(--y),
rgb(255 255 255) 20%,
rgb(255 255 255 / 25%),
transparent
);
這段代碼中,calc(var(--card-size) * 0.8) 是用來確定漸變區域的大小,這裏代表的是卡片尺寸的80%。
circle at var(--x) var(--y) 是用來設置漸變的位置,這裏的位置即跟隨鼠標移動變化着。
接下來的顏色部分是定義了漸變的顏色變化,從rgb(255 255 255)開始,顏色逐漸變淡到透明。最後的 transparent 是漸變的結束顏色,也就是mask的透明區域。
這段代碼創建了一個放射狀的漸變效果,用於遮罩一個元素,使得該元素只有部分可見。增加後的效果如下:
漸變色文本效果
觀察文章開始的完整效果可以發現漸變顏色的區域是沒有發生變化的,因為有陰影的變化讓人感覺漸變顏色似乎也在跟着變化。這裏主要用到了混合模式,混合模式用於控制兩個圖層在疊加時的顯示方式。我們的文本mask漸變是不斷變化的,那我們只需要在卡片上再設置一個漸變背景色就可以達到混合模式的效果。
這裏我們對card-gradient元素通過radial-gradient增加漸變背景色,效果如下圖所示,中心部分保留暗色,剩餘部分設置兩個漸變顏色。
--background-light-rgb: 30 41 59;
--hyperplexed-main-rgb: 41 121 255;
--hyperplexed-main-light-rgb: 56 182 255;
--hyperplexed-secondary-rgb: 42 252 152;
background: radial-gradient(
rgb(var(--background-light-rgb)) 40%,
rgb(var(--hyperplexed-main-rgb)) 50%,
rgb(var(--hyperplexed-main-light-rgb)),
rgb(var(--hyperplexed-secondary-rgb))
);
設置完成後的效果:
來到了關鍵的一步,設置混合模式darken。通過設置混合模式mix-blend-mode: darken表示當前圖層的顏色會通過與背景的顏色的減法運算來決定最終顯示的顏色。也就是説這個元素如果背景顏色較深,那麼元素的顏色將會變得更暗,反之則會變得更亮。回顧我們設置文本陰影部分,只有鼠標周圍是亮色,其他都是深色陰影,這樣結合上面的漸變背景即可應用到文本的顏色,通過下圖更清晰的展示的設置前後的區別。
結語
本文詳細解析了用代碼實現一個炫酷鼠標懸停漸變隨機文本的動畫效果,將這個效果應用到你的網站中,相信會大大的提升用户交互體驗。有興趣的朋友可以嘗試看看~
關注公眾號回覆【 20240102 】可獲取完整源代碼~
參考
evervault.com/customers
codepen.io/Hyperplexed/pen/VwqLQbo
看完本文如果覺得有用,記得點個贊支持,收藏起來説不定哪天就用上啦~
專注前端開發,分享前端相關技術乾貨,公眾號:南城大前端(ID: nanchengfe)