前言

在掘金逛到这篇文章(一个鼠标滑过的样式~ - 掘金 (juejin.cn)),模拟实现h3 - The Web Framework for Modern JavaScript Era (unjs.io)的鼠标滑动样式,如下。但仔细看,掘金这篇文章和原处的实现的效果不太一致,于是自己研究了一下,大程度上还原了。
gif1

我实现的

gif2

直接上代码

用的vue3模板,自行转换

<template>
<div class="container">
<div class="container-item" v-for="item in 8" :key="item">
<div class="container-item-content"></div>
</div>
</div>
</template>

<script setup>
import { onMounted } from 'vue'

// 获取鼠标位置
const calBoxesPosition = e => {
const { clientX, clientY } = e
const items = document.querySelectorAll('.container-item')
items.forEach(i => {
const { x, y } = i.getBoundingClientRect()
i.setAttribute('style', `--x: ${clientX - x}px; --y: ${clientY - y}px`)
})
}
onMounted(() => {
window.addEventListener('mousemove', calBoxesPosition)
})
</script>

<style lang="scss" scoped>
.container {
--color-background: 23 23 23;
--color-font: #fff;
--color-border: #222222;
--bg-color: #2dd4bf;
--bg-opacity: 1;
width: 1500px;
padding: 20px;
height: 800px;
background-color: rgb(var(--color-background));
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(3, 1fr);
grid-gap: 20px;
.container-item {
color: var(--color-font);
border-radius: 12px;
box-shadow: 0 0 1px 1px var(--color-border);
position: relative;
transition: background 0.5s ease-in-out;
&::before {
position: absolute;
display: block;
content: '';
z-index: 2;
width: calc(100% + 4px);
height: calc(100% + 4px);
inset: -2px;
border-radius: 12px;
background: radial-gradient(250px circle at var(--x) var(--y), var(--bg-color) 0, transparent 100%);
will-change: background;
}
.container-item-content {
border-radius: 12px;
background-color: rgb(var(--color-background) / var(--bg-opacity));
width: 100%;
position: relative;
z-index: 3;
padding: 20px;
height: 100%;
&:hover {
--bg-opacity: 0.9;
}
}
}
}
</style>

重点分析

伪元素:before

&::before {
position: absolute;
display: block;
content: '';
z-index: 2;
width: calc(100% + 4px);
height: calc(100% + 4px);
inset: -2px;
border-radius: 12px;
background: radial-gradient(250px circle at var(--x) var(--y), var(--bg-color) 0, transparent 100%);
will-change: background;
}

为了实现container-item元素周围鼠标滑动的炫光,需要用一个比它大的盒子包围它,这里用伪元素,width和height是父元素的100%+4px,再通过inset整体偏移回去2px,则可实现包围container-item,2px的空隙可存放炫光。

炫光形成:

​ 以鼠标为圆心,做一圆,半径为250px,颜色渐变.伪元素背景为radial-gradient,渐变起始点为圆心,终点为透明。当鼠标靠近container-item时,圆在伪元素可视区域内,颜色渐变,形成炫光。

确定圆心:

实时通过鼠标的位置坐标,拿到鼠标到container-item的距离,因为是伪元素是对container-item相对定位的,因此不能直接用鼠标的位置坐标为圆心

will-change 是一个CSS属性,它允许开发者告知浏览器某些元素将要发生的变化,以便浏览器可以提前进行优化,从而在变化实际发生时提供更平滑的动画和过渡效果。

z-index

需注意的是,z-index生效的条件是,元素有定位,且不是static。
container-item下面还有一层container-item-content,该元素撑大充满container-item,并且z-index要比伪元素大,将伪元素与container-item交叉区域覆盖,伪元素的炫光就只在周围出现。当鼠标移入container-item时,可通过:hover将container-item-content的背景颜色opacity降低一点,就会出现淡淡的炫光效果在item内。

参考

一个鼠标滑过的样式~ - 掘金 (juejin.cn)

h3 - The Web Framework for Modern JavaScript Era (unjs.io)