返回动效库
指针高级

聚光灯卡片

鼠标在卡片上方移动时,呈现手电筒照亮卡片局部的光影跟随效果。

悬停时continuous

交互预览

动效定义与代码

{
  "slug": "spotlight-card",
  "name": "聚光灯卡片",
  "nameEn": "Spotlight Card",
  "description": "鼠标在卡片上方移动时,呈现手电筒照亮卡片局部的光影跟随效果。",
  "descriptionEn": "A flashlight-like spotlight follows the cursor when hovering over the card.",
  "category": "micro-interaction",
  "tags": [
    "hover",
    "spotlight",
    "glow",
    "mouse-tracking"
  ],
  "trigger": "on-hover",
  "difficulty": "advanced",
  "duration": "continuous",
  "easing": "linear",
  "cssProperties": [
    "background-image"
  ],
  "isGPUAccelerated": true,
  "previewBg": "dark",
  "keywords": [
    "spotlight",
    "mouse tracking",
    "glow",
    "card effect",
    "lighting"
  ],
  "useCases": [
    "Pricing feature cards",
    "Bento grid items",
    "Portfolio project showcase"
  ],
  "relatedAnimations": [
    "hover-glow"
  ],
  "recommendedStyles": [
    "glassmorphism",
    "dark-mode",
    "modern-gradient"
  ],
  "codeSnippets": [
    {
      "label": "Tailwind CSS + React",
      "language": "tsx",
      "code": "import { useRef, useState } from \"react\";\n\nexport function SpotlightCard({ children }: { children: React.ReactNode }) {\n  const divRef = useRef<HTMLDivElement>(null);\n  const [position, setPosition] = useState({ x: 0, y: 0 });\n  const [opacity, setOpacity] = useState(0);\n\n  const handleMouseMove = (e: React.MouseEvent<HTMLDivElement>) => {\n    if (!divRef.current) return;\n    const rect = divRef.current.getBoundingClientRect();\n    setPosition({ x: e.clientX - rect.left, y: e.clientY - rect.top });\n  };\n\n  return (\n    <div\n      ref={divRef}\n      onMouseMove={handleMouseMove}\n      onMouseEnter={() => setOpacity(1)}\n      onMouseLeave={() => setOpacity(0)}\n      className=\"relative overflow-hidden border border-white/10 bg-black/20 p-8\"\n    >\n      <div\n        className=\"pointer-events-none absolute -inset-px transition-opacity duration-300\"\n        style={{\n          opacity,\n          background: `radial-gradient(600px circle at ${position.x}px ${position.y}px, rgba(255,255,255,0.1), transparent 40%)`,\n        }}\n      />\n      <div className=\"relative z-10\">{children}</div>\n    </div>\n  );\n}"
    },
    {
      "label": "Framer Motion",
      "language": "tsx",
      "code": "import { useRef } from \"react\";\nimport { motion, useMotionValue, useSpring } from \"framer-motion\";\n\n// Tip: consider disabling for reduced motion users\n// import { useReducedMotion } from \"framer-motion\";\n\nexport function SpotlightCard({ children }: { children: React.ReactNode }) {\n  const ref = useRef<HTMLDivElement>(null);\n  const mouseX = useMotionValue(0);\n  const mouseY = useMotionValue(0);\n  const opacity = useMotionValue(0);\n\n  const smoothX = useSpring(mouseX, { stiffness: 300, damping: 30 });\n  const smoothY = useSpring(mouseY, { stiffness: 300, damping: 30 });\n\n  const handleMouseMove = (e: React.MouseEvent<HTMLDivElement>) => {\n    if (!ref.current) return;\n    const rect = ref.current.getBoundingClientRect();\n    mouseX.set(e.clientX - rect.left);\n    mouseY.set(e.clientY - rect.top);\n  };\n\n  return (\n    <div\n      ref={ref}\n      onMouseMove={handleMouseMove}\n      onMouseEnter={() => opacity.set(1)}\n      onMouseLeave={() => opacity.set(0)}\n      className=\"relative overflow-hidden border border-white/10 bg-black/20 p-8\"\n    >\n      <motion.div\n        className=\"pointer-events-none absolute -inset-px\"\n        style={{\n          opacity,\n          background: `radial-gradient(600px circle at ${smoothX}px ${smoothY}px, rgba(255,255,255,0.1), transparent 40%)`,\n        }}\n      />\n      <div className=\"relative z-10\">{children}</div>\n    </div>\n  );\n}"
    }
  ]
}