如图所示,这是一个很炫酷的按钮悬浮特效,鼠标悬停时,按钮呈现发光的效果,周边还出现类型萤火虫的效果。本文将解析如何实现这个按钮特效,基于这个动图可以分析出需要实现的要点:
- 有一个跟随鼠标移动的圆点
- 按钮悬停时有高亮发光的效果
- 悬停时按钮周边的萤火中效果
实现过程
跟随鼠标移动的圆点
这个部分需要基于JS实现,但不是最主要的实现代码
如果单纯做一个跟随鼠标移动的点很简单,只需要监听鼠标事件获取坐标实时更新到需要移动的元素上即可。但是仔细看这里的效果并不是这样,圆点是跟随在鼠标后面,鼠标移动停止后圆点才会和鼠标重合。这里是使用了一个名为 Kinet
的库来实现的这个鼠标移动动画效果,具体实现如下:
- 创建 Kinet 实例,传入了自定义设置:
- acceleration: 加速度,控制动画的加速程度。
- friction: 摩擦力,控制动画的减速程度。
- names: 定义了两个属性 x 和 y,用于表示动画的两个维度。
1 var kinet = new Kinet({
2 acceleration: 0.02,
3 friction: 0.25,
4 names: ["x", "y"],
5 });
- 通过 document.getElementById 获取页面中 ID 为
circle
的元素,以便后续进行动画处理。
1var circle = document.getElementById('circle');
- 设置 Kinet 的
tick
事件处理:
- 监听
tick
事件,每当 Kinet 更新时执行该函数。 instances
参数包含当前的 x 和 y 值及其速度。- 使用
style.transform
属性来更新圆形元素的位置和旋转: translate3d
用于在 3D 空间中移动元素。rotateX
和rotateY
用于根据当前速度旋转元素。
1 kinet.on('tick', function(instances) {
2 circle.style.transform = `translate3d(${ (instances.x.current) }px, ${ (instances.y.current) }px, 0) rotateX(${ (instances.x.velocity/2) }deg) rotateY(${ (instances.y.velocity/2) }deg)`;
3 });
- 听 mousemove 事件,
kinet.animate
方法用于更新 x 和 y 的目标值,计算方式是将鼠标的当前位置减去窗口的中心位置,使动画围绕窗口中心进行。
1 document.addEventListener('mousemove', function (event) {
2 kinet.animate('x', event.clientX - window.innerWidth/2);
3 kinet.animate('y', event.clientY - window.innerHeight/2);
4 });
随着鼠标的移动这个圆点元素将在页面上进行平滑的动画。通过 Kinet 库的加速度和摩擦力设置,动画效果显得更加自然,用户体验更加生动。有兴趣的可以尝试调整参数解锁其他玩法,此时我们的页面效果如下:
按钮悬停时发光效果
这里主要通过悬停时设置transition
过渡改变按钮的内外阴影效果,阴影效果通过伪元素实现,默认透明度为0,按钮样式代码如下:
1.button {
2 z-index: 1;
3 position: relative;
4 text-decoration: none;
5 text-align: center;
6 appearance: none;
7 display: inline-block;
8}
9
10.button::before, .button::after {
11 content: "";
12 position: absolute;
13 top: 0;
14 right: 0;
15 left: 0;
16 bottom: 0;
17 border-radius: 999px;
18 opacity: 0;
19 transition: opacity 0.3s;
20}
21
22.button::before {
23 box-shadow: 0px 0px 24px 0px #FFEB3B;
24}
25
26.button::after {
27 box-shadow: 0px 0px 23px 0px #FDFCA9 inset, 0px 0px 8px 0px #FFFFFF42;
28}
当鼠标悬停在按钮上时,通过改变伪元素的透明度,使发光效果在鼠标悬停时变得可见:
1.button-wrapper:hover .button::before,
2.button-wrapper:hover .button::after {
3 opacity: 1;
4}
此时的按钮效果如下:
悬停时萤火中效果
如头部图片所展示,萤火虫效果是有多个圆点散开,所以这里我们添加多个圆点元素。
1 <span class="dot dot-1"></span>
2 <span class="dot dot-2"></span>
3 <span class="dot dot-3"></span>
4 <span class="dot dot-4"></span>
5 <span class="dot dot-5"></span>
6 <span class="dot dot-6"></span>
7 <span class="dot dot-7"></span>
设置元素样式,这里的CSS变量(如 —speed, —size, —starting-x, —starting-y, —rotatation)用于控制圆点的动画速度、大小、起始位置和旋转角度。
1.dot {
2 display: block;
3 position: absolute;
4 transition: transform calc(var(--speed) / 12) ease;
5 width: var(--size);
6 height: var(--size);
7 transform: translate(var(--starting-x), var(--starting-y)) rotate(var(--rotatation));
8}
给圆点设置动画效果,使用 @keyframes
定义了两个动画:dimFirefly
和 hoverFirefly
,为圆点添加了闪烁和移动效果:
1@keyframes dimFirefly {
2 0% { opacity: 1; }
3 25% { opacity: 0.4; }
4 50% { opacity: 0.8; }
5 75% { opacity: 0.5; }
6 100% { opacity: 1; }
7}
8
9@keyframes hoverFirefly {
10 0% { transform: translate(0, 0); }
11 12% { transform: translate(3px, 1px); }
12 24% { transform: translate(-2px, 3px); }
13 37% { transform: translate(2px, -2px); }
14 55% { transform: translate(-1px, 0); }
15 74% { transform: translate(0, 2px); }
16 88% { transform: translate(-3px, -1px); }
17 100% { transform: translate(0, 0); }
18}
在圆点的伪元素上关联动画效果:
1.dot::after {
2 content: "";
3 animation: hoverFirefly var(--speed) infinite, dimFirefly calc(var(--speed) / 2) infinite calc(var(--speed) / 3);
4 animation-play-state: paused;
5 display: block;
6 border-radius: 100%;
7 background: yellow;
8 width: 100%;
9 height: 100%;
10 box-shadow: 0px 0px 6px 0px #FFEB3B, 0px 0px 4px 0px #FDFCA9 inset, 0px 0px 2px 1px #FFFFFF42;
11}
给每个圆点设置不同的动画参数,通过使用 CSS 变量,开发者可以灵活地控制每个 .dot
元素的旋转角度,进一步丰富视觉效果。
1.dot-1 {
2 --rotatation: 0deg;
3 --speed: 14s;
4 --size: 6px;
5 --starting-x: 30px;
6 --starting-y: 20px;
7 top: 2px;
8 left: -16px;
9 opacity: 0.7;
10}
11
12.dot-2 {
13 --rotatation: 122deg;
14 --speed: 16s;
15 --size: 3px;
16 --starting-x: 40px;
17 --starting-y: 10px;
18 top: 1px;
19 left: 0px;
20 opacity: 0.7;
21}
22...
此时只要在父元素.button-wrapper
悬停时,则触发 .dot
元素的旋转效果,并使其伪元素的动画开始运行,此时萤火中悬停效果就会开始运行。
1.button-wrapper:hover {
2 .dot {
3 transform: translate(0, 0) rotate(var(--rotatation));
4 }
5
6 .dot::after {
7 animation-play-state: running;
8 }
9}
最后完成的悬停效果如下:
在线预览
最后
通过以上步骤,结合现代 CSS 的强大功能,我们实现了一个发光的萤火虫圆点悬停按钮效果。这样的效果不仅提升了视觉吸引力,还增强了用户的交互体验。利用 CSS 变量和动画,设计师可以灵活地控制每个元素的表现,使得网页更加生动和引人注目。有兴趣的可以调整相关参数体验其他的视觉效果。
看完本文如果觉得有用,记得点个赞支持,收藏起来说不定哪天就用上啦~
专注前端开发,分享前端相关技术干货,公众号:南城大前端(ID: nanchengfe)