3D 透视倾斜
鼠标在卡片上移动时,卡片随鼠标位置产生 3D 透视倾斜效果,营造沉浸式的空间深度感。
交互预览
动效定义与代码
{
"slug": "tilt-3d",
"name": "3D 透视倾斜",
"nameEn": "3D Tilt",
"description": "鼠标在卡片上移动时,卡片随鼠标位置产生 3D 透视倾斜效果,营造沉浸式的空间深度感。",
"descriptionEn": "Card tilts in 3D space following cursor position, creating an immersive depth effect with perspective transforms.",
"category": "hover",
"tags": [
"3d",
"perspective",
"tilt",
"hover",
"mouse-tracking",
"interactive"
],
"trigger": "on-hover",
"difficulty": "intermediate",
"duration": "continuous",
"easing": "ease-out",
"cssProperties": [
"transform",
"perspective"
],
"isGPUAccelerated": true,
"previewBg": "dark",
"keywords": [
"3d tilt",
"perspective",
"mouse tracking",
"card hover",
"parallax card",
"depth"
],
"useCases": [
"Product showcase cards",
"Pricing cards",
"Portfolio project cards",
"Image gallery thumbnails"
],
"relatedAnimations": [
"hover-lift",
"spotlight-card",
"magnetic-hover"
],
"recommendedStyles": [
"glassmorphism",
"dark-mode",
"cyberpunk-neon",
"apple-style"
],
"codeSnippets": [
{
"label": "CSS Keyframes",
"language": "css",
"code": "/* 3D Tilt requires JS for mouse tracking.\n CSS sets up the perspective container and smooth transitions. */\n\n.tilt-container {\n perspective: 1000px;\n}\n\n.tilt-card {\n transform-style: preserve-3d;\n transition: transform 150ms ease-out;\n will-change: transform;\n}\n\n.tilt-card:hover {\n /* JS overrides this with dynamic rotateX/rotateY values */\n transform: rotateX(var(--tilt-x, 0deg)) rotateY(var(--tilt-y, 0deg)) scale3d(1.02, 1.02, 1.02);\n}\n\n.tilt-card .tilt-shine {\n position: absolute;\n inset: 0;\n background: radial-gradient(\n circle at var(--mouse-x, 50%) var(--mouse-y, 50%),\n rgba(255, 255, 255, 0.15),\n transparent 60%\n );\n pointer-events: none;\n opacity: 0;\n transition: opacity 150ms ease-out;\n}\n\n.tilt-card:hover .tilt-shine {\n opacity: 1;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .tilt-card {\n transition: none;\n transform: none !important;\n }\n .tilt-card .tilt-shine {\n display: none;\n }\n}"
},
{
"label": "Tailwind CSS",
"language": "css",
"code": "/* Tailwind v4 — 3D Tilt container and card */\n\n@utility perspective-1000 {\n perspective: 1000px;\n}\n\n@utility preserve-3d {\n transform-style: preserve-3d;\n}\n\n/* Usage:\n <div class=\"perspective-1000\">\n <div class=\"preserve-3d transition-transform duration-150 ease-out hover:scale-[1.02]\"\n style=\"transform: rotateX(var(--tilt-x)) rotateY(var(--tilt-y))\">\n Card content\n </div>\n </div>\n*/"
},
{
"label": "Framer Motion",
"language": "tsx",
"code": "\"use client\";\n\nimport { motion, useMotionValue, useSpring } from \"framer-motion\";\nimport { type MouseEvent, type ReactNode } from \"react\";\n\ninterface Tilt3DProps {\n children: ReactNode;\n maxTilt?: number;\n className?: string;\n}\n\nexport function Tilt3D({ children, maxTilt = 15, className }: Tilt3DProps) {\n const rotateX = useMotionValue(0);\n const rotateY = useMotionValue(0);\n const springX = useSpring(rotateX, { stiffness: 300, damping: 20 });\n const springY = useSpring(rotateY, { stiffness: 300, damping: 20 });\n\n function handleMouseMove(e: MouseEvent<HTMLDivElement>) {\n const rect = e.currentTarget.getBoundingClientRect();\n const x = (e.clientX - rect.left) / rect.width - 0.5;\n const y = (e.clientY - rect.top) / rect.height - 0.5;\n rotateX.set(-y * maxTilt);\n rotateY.set(x * maxTilt);\n }\n\n function handleMouseLeave() {\n rotateX.set(0);\n rotateY.set(0);\n }\n\n return (\n <div style={{ perspective: 1000 }}>\n <motion.div\n className={className}\n onMouseMove={handleMouseMove}\n onMouseLeave={handleMouseLeave}\n style={{\n rotateX: springX,\n rotateY: springY,\n transformStyle: \"preserve-3d\",\n }}\n >\n {children}\n </motion.div>\n </div>\n );\n}"
}
]
}