# 3D 倾斜 Tilt > 卡片跟着鼠标往不同方向微微倾斜,表面的高光跟着移动,离开后平稳回正。 分类:动效 · 角色:点缀(贴在某个元素上,一页两三个) [全部组件和流程](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 - 放在:卡片 - 手机上:没效果:手机上就是一张静止的卡。 - 性能代价:低:只改 transform。 - 常搭配:[磁吸 Magnetic](https://www.dachuiai.com/c/magnetic.md)、[滚动出现 Scroll Reveal](https://www.dachuiai.com/c/scroll-reveal.md) ## 装进项目 - 写法:React 18 以上 + TypeScript + Tailwind CSS v4,一个文件就能用,不引用别的组件。 - 依赖:只用 react,不用另外安装 - 文件:原样存成 `tilt.tsx`(比如 `src/components/tilt.tsx`)。能跑命令就下载[原文](https://www.dachuiai.com/code/tilt.tsx),比手抄准:`curl -fsSL -o src/components/tilt.tsx https://www.dachuiai.com/code/tilt.tsx`(Windows 写 `curl.exe`)。下载完看一眼第一行是 `import`,不是网页。 - 导出:`Tilt` 是可以直接用的部分;最后的 `export default` 是演示示例,只作参考。 - 图片:示例用了本站的 [/tex/gold.jpg](https://www.dachuiai.com/tex/gold.jpg)。换成用户自己的图;只想先看效果,可以从本站同样的路径下载,放进项目的 public 目录。 - 注意:radius 和卡片圆角一致;max 是最大倾斜角度。 - 保留代码里 `prefers-reduced-motion` 的处理:用户开了「减弱动态效果」时内容照样完整显示。 - 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、有赞这类建站平台装不进代码,告诉用户去平台自带的动效设置里找。 ## 参数 | 参数 | 默认值 | 作用 | | --- | --- | --- | | `children` | | 包在里面的内容 | | `max` | `14` | 最多倾斜几度 | | `className` | `''` | 加在最外层的类名,用来调大小、位置、间距 | | `radius` | `24` | 圆角(px),和卡片的圆角保持一致 | ## 你可以说 > 会员卡做成 3D Tilt 倾斜效果:卡片跟着鼠标往不同方向微微倾斜,表面的高光跟着移动,鼠标离开后平稳回正。 ## 完整代码 ```tsx import {useRef, useState, type ReactNode} from 'react'; /* --------------------------------------------------------------- * Tilt 3D 倾斜 * 卡片跟着鼠标的位置往不同方向微微倾斜,表面的反光也跟着移动, * 像拿在手里转着看。鼠标离开后平稳回正。 * ------------------------------------------------------------- */ type TiltProps = {children: ReactNode; max?: number; className?: string; radius?: number}; export function Tilt({children, max = 14, className = '', radius = 24}: TiltProps) { const ref = useRef(null); const [s, setS] = useState({rx: 0, ry: 0, gx: 50, gy: 50, on: false}); const reduce = typeof window !== 'undefined' && window.matchMedia('(prefers-reduced-motion: reduce)').matches; const move = (e: React.PointerEvent) => { const r = ref.current!.getBoundingClientRect(); const px = (e.clientX - r.left) / r.width, py = (e.clientY - r.top) / r.height; setS({rx: (0.5 - py) * max, ry: (px - 0.5) * max * 1.3, gx: px * 100, gy: py * 100, on: true}); }; const leave = () => setS({rx: 0, ry: 0, gx: 50, gy: 50, on: false}); const t = reduce ? {rx: 0, ry: 0} : s; return (
{children} {/* 跟着鼠标移动的高光 */}
); } /* ---------------- 示例:金色会员卡(拉丝金属纹理 /tex/gold.jpg) ---------------- */ const ink = 'rgba(70,44,8,.88)'; const emboss = '0 1px 0 rgba(255,246,220,.6), 0 -1px 0 rgba(70,44,8,.35)'; export default function TiltDemo() { return (
{Array.from({length: 14}, (_, i) => ( `L${j * 20} ${(18 + i * 19 + Math.sin(j * 20 / 34 + i * 0.55) * 8).toFixed(1)}`).join(' ')}`} fill="none" stroke="rgba(92,60,14,.12)" strokeWidth="1" /> ))} {Array.from({length: 9}, (_, i) => )}
PRIME 会员卡
6688 2026 0529 8888
VIP MEMBER VALID THRU 12/30
); } ```