今天分享一个很有特色的按钮交互效果,保证让你停不下来,原作者是Adam Kuhn,有兴趣的可以去 codepen 体验,地址:codepen,本文将核心功能逐一讲解,以下是在线效果图:
主要实现的几个功能点拆分为以下几点:
- 按钮的径向渐变背景色可以随着鼠标的移动变化
- 按钮的背景区域会随着鼠标的移动产生弹性变化效果
- 按钮的文字阴影会随着鼠标的变化而变化
鼠标位置获取
在正式开始前做一些准备工作,分析主要的这几个功能点可以发现每个功能都和鼠标的移动有关,都需要借助于鼠标移动的坐标,所以我们首先获取鼠标的位置并传递到 css 中,代码如下:
document.querySelectorAll(".inner").forEach((button) => {
button.onmousemove = (e) => {
const target = e.target;
const rect = target.getBoundingClientRect();
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
button.style.setProperty("--x", `${x}px`);
button.style.setProperty("--y", `${y}px`);
button.style.setProperty("--height", `${rect.height}px`);
button.style.setProperty("--width", `${rect.width}px`);
};
});
这里除开传递鼠标的位置,还传递了当前按钮的宽高用于后续按钮文案阴影的依赖。
径向渐变背景动起来
背景色默认是纯色,随着鼠标的产生变化,所以这里和两个关键点有关,鼠标移入 hover,移动过程中的坐标变化。实现过程核心是通过 background 定义两个背景色,默认的显示部分background-size是 100%,渐变部分的background-size是 0,待 hover 时设置为 100%,这时就会显示渐变背景色内容了。
background:
// 渐变背景色
radial-gradient(
circle at center,
var(--lightest),
var(--light) 5%,
var(--dark) 30%,
var(--darkest) 50%
),
// 默认显示背景色
var(--darkest);
background-size: 0px 0px, 100%;
:hover {
background-size: 100%, 100%;
}
显示之后要动起来,基于 js 传入的坐标值应用到transform的translate平移,这里注意移动是要基于当前元素的中心点位所以 x 和 y 都要减去自身的 50%。
transform: translate(calc(var(--x) - 50%), calc(var(--y) - 50%));
如图所示,绿色区域是按钮部分,整个背景的中心点要和鼠标移动的坐标一致,所以要减去自身宽高的各一半。还有一点需要注意的是不能在移动的过程中让背景色漏出,所以背景区域是整个按钮的 2 倍。

结语
到此整个核心的实现过程就结束了,整个代码中我们使用了box-shadow,text-shadow,mix-blend-mode,filter等属性,还有 CSS3 函数max,clamp,calc。还有transition动画相关没有说明,涉及的知识点比较多,有兴趣的同学可以看源码了解。