【CSS】卡片hover效果跟着鼠标动

2024-07-08  本文已影响0人  JellyL

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
        );
    }
}
上一篇下一篇

猜你喜欢

热点阅读