如图所示,这是一个很炫酷的鼠标悬停动画效果,卡片的文字随着鼠标的移动不断变化着,且文字的颜色伴随着渐变色跟随鼠标移动,中心部分是突出的LOGO效果,整个交互效果十分引人注目。原效果来源于 evervault.com/customers
这个网站,有兴趣的可以体验看看~
本次文章将解析如何用代码实现这个效果,根据上面的动图分析出我们要实现的几个主要功能点:
根据上面的分析中心的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)