
<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 } = edocument.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");})}
