3

如图所示,这是一个很炫酷的鼠标悬停动画效果,卡片的文字随着鼠标的移动不断变化着,且文字的颜色伴随着渐变色跟随鼠标移动,中心部分是突出的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";

然后定义随机字符的函数,这段代码定义了两个函数:randomCharrandomString

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)


南城FE
2.2k 声望571 粉丝