<template>
<div id="app">
<ul @pointermove="handlePointerMove($event)">
<li v-for="item in cards" :key="item.name">
<h5>{{ item.name }}</h5>
<p>{{ item.desc }}</p>
</li>
</ul>
</div>
</template>
<script setup lang="ts">
const cards = [
{
name: 'Falcomon',
desc: 'A bird-shaped Monster.',
},
{
name: 'Labramon',
desc: 'A Beast monster that resembles a real dog.',
},
{
name: 'Agumon',
desc: 'A monster resembling a small dinosaur.',
},
{
name: 'Floramon',
desc: 'A Vegetation monster. ',
},
{
name: 'Kunemon',
desc: 'A Larva monster with a lightning pattern on his body.',
},
{
name: 'Lopmon',
desc: 'His ecosystem is wrapped in mystery, and his composition is enough to deem him a Beast monster.',
},
]
const handlePointerMove = (e: any) => {
const { clientX, clientY } = e
document.querySelectorAll('li').forEach((item) => {
const { left, top } = item.getBoundingClientRect()
item.style.setProperty('--x', `${clientX - left}px`)
item.style.setProperty('--y', `${clientY - top}px`)
})
}
</script>
<style lang="scss">
@import url('https://fonts.googleapis.com/css?family=Press+Start+2P');
#app {
width: 100%;
min-height: 100vh;
background-color: #333;
padding: 0.5em;
}
ul {
width: 100%;
display: grid;
grid-column-gap: 0.5em;
grid-row-gap: 0.5em;
grid-template-columns: repeat(3, 1fr);
li {
border: 2px solid rgba(121, 67, 117, 0.3);
position: relative;
box-sizing: border-box;
padding: 0.4em 0.8em 0.7em;
font-family: 'Press Start 2P', sans-serif;
background-color: rgba(90, 24, 171, 0.05);
border-radius: 15px;
line-height: 1.6;
color: rgba(255, 255, 255, 0.36);
transition: 1s color;
h5 {
font-size: 1.5em;
margin-bottom: 0.5em;
color: inherit;
}
p {
font-size: 1.2em;
color: inherit;
}
&:hover {
color: rgba(255, 255, 255, 1);
}
&::after {
content: '';
display: block;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
inset: 0;
border-radius: inherit;
background: radial-gradient(
300px circle at var(--x) var(--y),
rgba(255, 255, 255, 0.25),
transparent 50%
);
z-index: 2;
transition: all 0.5s ease;
opacity: 0;
}
}
&:hover {
li::after {
opacity: 1;
}
}
}
</style>
添加灯光
通过伪元素radial-gradient
添加一个渐变色的浅白圈
li {
&::after {
background: radial-gradient(
600px circle at var(--x) var(--y),
rgba(255, 255, 255, 0.25),
transparent 50%
)
}
}
跟随移动
通过父元素上的handlePointerMove
方法,监听pointermove
事件,鼠标每次移动到父元素,就遍历每一个子元素算出当前坐标,通过setProperty
改变css变量
handlePointerMove(e) {
const { clientX, clientY } = e;
document.querySelectorAll("li").forEach(item => {
const { left, top } = item.getBoundingClientRect();
item.style.setProperty("--x", clientX - left + "px");
item.style.setProperty("--y", clientY - top + "px");
})
}