# 聚光 Spotlight > 鼠标移到哪里,哪里就有一团光跟着走,经过的卡片边框也被照亮。 分类:动效 · 角色:点缀(贴在某个元素上,一页两三个) [全部组件和流程](https://www.dachuiai.com/llms.txt) · [动效选型规则](https://www.dachuiai.com/guides/motion.md) ## 给 AI:用户把这个组件发给了你 1. 先看用户的项目:框架、页面类型、现在的风格、手机还是电脑为主。 2. 对照下面的「适合 / 不适合」判断合不合适。不合适就直接说,并从[动效选型规则](https://www.dachuiai.com/guides/motion.md)或[全部组件](https://www.dachuiai.com/llms.txt)里另挑一个。 3. 合适就按「装进项目」装好,示例里的文字和图片换成用户自己的。 4. 告诉用户用了什么、放在哪个文件、以后想改快慢、颜色、大小改哪个参数。 ## 什么时候用 - 适合:深色背景上的一排功能卡片。 - 不适合:浅色背景(光看不出来);以手机访问为主的页面。 - 适合的网站:SaaS、官网、作品集 - 放在:卡片 - 手机上:没效果:手机上就是普通卡片。 - 性能代价:低:只改两个 CSS 变量。 - 常搭配:[边缘流光 Border Beam](https://www.dachuiai.com/c/border-beam.md)、[滚动出现 Scroll Reveal](https://www.dachuiai.com/c/scroll-reveal.md) ## 装进项目 - 写法:React 18 以上 + TypeScript + Tailwind CSS v4,一个文件就能用,不引用别的组件。 - 依赖:`npm i lucide-react` - 文件:原样存成 `spotlight.tsx`(比如 `src/components/spotlight.tsx`)。能跑命令就下载[原文](https://www.dachuiai.com/code/spotlight.tsx),比手抄准:`curl -fsSL -o src/components/spotlight.tsx https://www.dachuiai.com/code/spotlight.tsx`(Windows 写 `curl.exe`)。下载完看一眼第一行是 `import`,不是网页。 - 导出:`SpotlightGroup`、`SpotlightCard` 是可以直接用的部分;最后的 `export default` 是演示示例,只作参考。 - 注意:把一组卡片放进 SpotlightGroup,相邻卡片的边框会被同一团光照到。 - Next.js(有 app 文件夹):文件第一行加 `'use client';`。 - 用 JavaScript 不用 TypeScript:Vite 和 Next.js 都能直接用 .tsx 文件;也可以删掉类型标注,改名 .jsx。 - 没有 Tailwind:先装 Tailwind CSS v4(Vite 项目 `npm i tailwindcss @tailwindcss/vite`,vite 配置的 plugins 里加 `tailwindcss()`,入口引入的那个 CSS 文件(一般是 `src/index.css`)第一行写 `@import "tailwindcss";`),或者把类名改写成项目用的样式。 - 已经装了 Tailwind v3:别为了一个组件升级。类名大多通用,少数 v4 写法要换,比如焦点框 `outline-2` 在 v3 里要写成 `outline outline-2`。 - 不是 React(Vue、Svelte、小程序、纯 HTML):照着代码的做法改写,时长、曲线、参数保持一样。Wix、有赞这类建站平台装不进代码,告诉用户去平台自带的动效设置里找。 ## 参数 **SpotlightGroup** | 参数 | 默认值 | 作用 | | --- | --- | --- | | `children` | | 包在里面的内容 | | `className` | `''` | 加在最外层的类名,用来调大小、位置、间距 | **SpotlightCard** | 参数 | 默认值 | 作用 | | --- | --- | --- | | `children` | | 包在里面的内容 | | `className` | `''` | 加在最外层的类名,用来调大小、位置、间距 | | `color` | `'129,140,248'` | 颜色 | ## 你可以说 > 给这排功能卡片加 Spotlight 聚光效果:鼠标移到哪里,哪里就有一团光跟着走,经过的卡片边框也被照亮。 ## 完整代码 ```tsx import {useRef, type CSSProperties, type ReactNode} from 'react'; import {ArrowRight, Rocket, ShieldCheck, Sparkles} from 'lucide-react'; /* --------------------------------------------------------------- * Spotlight 聚光 * 鼠标在卡片上移动时,一团光跟着鼠标走,把卡片和边框照亮。 * 把一组卡片放进 ,相邻卡片的边框也会被同一团光照到。 * ------------------------------------------------------------- */ export function SpotlightGroup({children, className = ''}: {children: ReactNode; className?: string}) { const ref = useRef(null); const move = (e: React.PointerEvent) => { // 每张卡片记录鼠标相对自己的位置,CSS 用它画光 ref.current?.querySelectorAll('[data-spot]').forEach((card) => { const r = card.getBoundingClientRect(); card.style.setProperty('--x', `${e.clientX - r.left}px`); card.style.setProperty('--y', `${e.clientY - r.top}px`); }); }; return (
{children}
); } export function SpotlightCard({children, className = '', color = '129,140,248'}: {children: ReactNode; className?: string; color?: string}) { return (
{children}
); } const SPOT_CSS = ` .sp-card { --x: -999px; --y: -999px; background: radial-gradient(280px circle at var(--x) var(--y), rgba(var(--c), .9), rgba(148,163,184,.12) 60%); } .sp-inner::before { content: ''; position: absolute; inset: 0; pointer-events: none; opacity: 0; transition: opacity .3s; background: radial-gradient(320px circle at var(--x) var(--y), rgba(var(--c), .3), transparent 65%); } .sp-inner::after { content: ''; position: absolute; inset: 0; pointer-events: none; opacity: 0; transition: opacity .3s; background-image: radial-gradient(rgba(var(--c), .55) 1.2px, transparent 1.6px); background-size: 16px 16px; -webkit-mask: radial-gradient(180px circle at var(--x) var(--y), #000, transparent 75%); mask: radial-gradient(180px circle at var(--x) var(--y), #000, transparent 75%); } .group\\/spot:hover .sp-inner::before, .group\\/spot:hover .sp-inner::after { opacity: 1; } .sp-card { transition: background .2s; } `; /* ---------------- 示例:产品特性三张卡 ---------------- */ const FEATURES = [ {icon: Sparkles, title: '智能生成', text: '一句话描述,生成完整页面。'}, {icon: ShieldCheck, title: '安全可靠', text: '数据加密存储,权限分级管理。'}, {icon: Rocket, title: '极速部署', text: '一键发布,全球节点加速访问。'}, ]; export default function SpotlightDemo() { return (

为什么选择我们

从想法到上线,只需要一个下午

{FEATURES.map(({icon: Icon, title, text}) => (

{title}

{text}

了解更多
))}
); } ```