CSS+JS实现hover效果跟着鼠标动
// page
// const src = "https://i.pinimg.com/736x/f0/c3/23/f0c323f370acf6cf35973ca5f53ecc89.jpg";
const src = "https://oss.aiyuzhou8.com/2023/05/08-.jpg";
<div className="w-full h-full flex items-center bg-[#001] ">
<RotatingCard src={src} />
</div>
// RotatingCard
'use client';
import "./index.css";
import { useRef } from "react";
interface RotatingCardProps {
src: string;
}
const RotatingCard = ({ src }: RotatingCardProps) => {
const container = useRef<HTMLDivElement | null>(null);
const mask = useRef<HTMLDivElement | null>(null);
const handleContainerMouseMove = (event) => {
if (container.current && mask.current) {
mask.current.style.visibility = "visible";
const target = event.target;
const rect = target.getBoundingClientRect();
const offsetX = event.clientX - rect.left;
const offsetY = event.clientY - rect.top;
const percentX = (Math.min(Math.max(offsetX/rect.width, 0), 1) * 100).toFixed(2);
const percentY = (Math.min(Math.max(offsetY/rect.height, 0), 1) * 100).toFixed(2);
container.current?.setAttribute(
'style',
`--x: ${percentX}%; --y: ${percentY}%;--pic: url(${src});`
);
}
}
const handleContainerMouseOut = () => {
if (mask.current) {
mask.current.style.visibility = "hidden";
}
}
return (
<div
className="container"
ref={container}
onMouseOut={handleContainerMouseOut}
onMouseMove={handleContainerMouseMove}
style={{ "--pic": `url(${src})` }}
>
<div className="filter" style={{ "--pic": `url(${src})` }} />
<div className="mask" ref={mask} />
</div>
);
};
export default RotatingCard;
// index.css
:root {
--x: 0;
--y: 0;
--pic: url("https://oss.aiyuzhou8.com/2023/05/08-.jpg");
--borderRadius: 30px;
}
.container {
position: relative;
margin: auto;
width: 350px;
height: 500px;
border-radius: 30px;
transition: all 0.1s;
z-index: 3;
&::after {
content: "";
position: absolute;
inset: 50px;
background: var(--pic);
background-size: cover;
background-position: center;
border-radius: var(--borderRadius);
z-index: 10;
}
}
.filter {
position: absolute;
inset: 2px;
border-radius: var(--borderRadius);
z-index: 5;
overflow: hidden;
&::before {
content: "";
position: absolute;
inset: 0;
background: var(--pic);
background-size: cover;
filter: blur(20px);
}
}
.mask {
position: absolute;
filter: brightness(1.5);
inset: 0;
z-index: 1;
visibility: hidden;
mask: radial-gradient(
circle at var(--x) var(--y),
#000,
#000,
transparent,
transparent,
transparent
);
&::before {
content: "";
position: absolute;
inset: 2px;
border-radius: var(--borderRadius);
background: conic-gradient(
#03a9f4,
#e91e63,
#9c27b0,
#ff5722,
#03a9f4
);
}
&::after{
content: "";
position: absolute;
inset: 0;
border-radius: var(--borderRadius);
background: conic-gradient(
#03a9f4,
#e91e63,
#9c27b0,
#ff5722,
#03a9f4
);
}
}