nextjs-motion-animations
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseNext.js Motion Animation System
Next.js Motion 动画系统
A comprehensive animation system using Motion (formerly Framer Motion) v12.23.26 with performance-optimized patterns for Next.js applications.
一套基于 Motion(原 Framer Motion)v12.23.26 的全面动画系统,为 Next.js 应用提供性能优化的实现模式。
When to Use This Skill
何时使用该技能
Use this skill when you need to:
- Add scroll-triggered animations to sections
- Create interactive hover/tap animations
- Implement staggered animations for lists
- Add SVG path animations
- Set up a centralized animation system
- Optimize animation performance in Next.js
在以下场景中使用本技能:
- 为页面区块添加滚动触发动画
- 创建交互式悬停/点击动画
- 为列表实现交错动画
- 添加 SVG 路径动画
- 搭建集中式动画系统
- 优化 Next.js 中的动画性能
Core Animation Architecture
核心动画架构
Library Setup
库配置
- Primary: Motion v12.23.26 (modern, lightweight alternative to framer-motion)
- CSS Framework: TailwindCSS with custom animation utilities
- Compatibility: React 19+ and Next.js 16+
- 核心库:Motion v12.23.26(framer-motion 的现代轻量替代方案)
- CSS 框架:带有自定义动画工具类的 TailwindCSS
- 兼容性:React 19+ 和 Next.js 16+
Installation
安装步骤
bash
npm install motion@12.23.26bash
npm install motion@12.23.26Optional for CSS animations
可选:用于CSS动画
npm install tw-animate-css@1.4.0
undefinednpm install tw-animate-css@1.4.0
undefined1. Centralized Animation Variants
1. 集中式动画变体
Create with reusable variants:
src/lib/animations.tstypescript
// Basic fade animations with directional movement
export const fadeInUp = {
hidden: { opacity: 0, y: 30 },
visible: { opacity: 1, y: 0, transition: { duration: 0.6 } }
};
export const fadeInDown = {
hidden: { opacity: 0, y: -30 },
visible: { opacity: 1, y: 0, transition: { duration: 0.6 } }
};
export const fadeInLeft = {
hidden: { opacity: 0, x: -30 },
visible: { opacity: 1, x: 0, transition: { duration: 0.6 } }
};
export const fadeInRight = {
hidden: { opacity: 0, x: 30 },
visible: { opacity: 1, x: 0, transition: { duration: 0.6 } }
};
export const fadeInScale = {
hidden: { opacity: 0, scale: 0.8 },
visible: { opacity: 1, scale: 1, transition: { duration: 0.6 } }
};
// Container for staggered child animations
export const staggerContainer = {
hidden: { opacity: 0 },
visible: {
opacity: 1,
transition: { staggerChildren: 0.1, delayChildren: 0.2 }
}
};
// Individual items within staggered containers
export const staggerItem = {
hidden: { opacity: 0, y: 20 },
visible: { opacity: 1, y: 0, transition: { duration: 0.5 } }
};创建 文件,定义可复用的动画变体:
src/lib/animations.tstypescript
// 带有方向移动的基础淡入动画
export const fadeInUp = {
hidden: { opacity: 0, y: 30 },
visible: { opacity: 1, y: 0, transition: { duration: 0.6 } }
};
export const fadeInDown = {
hidden: { opacity: 0, y: -30 },
visible: { opacity: 1, y: 0, transition: { duration: 0.6 } }
};
export const fadeInLeft = {
hidden: { opacity: 0, x: -30 },
visible: { opacity: 1, x: 0, transition: { duration: 0.6 } }
};
export const fadeInRight = {
hidden: { opacity: 0, x: 30 },
visible: { opacity: 1, x: 0, transition: { duration: 0.6 } }
};
export const fadeInScale = {
hidden: { opacity: 0, scale: 0.8 },
visible: { opacity: 1, scale: 1, transition: { duration: 0.6 } }
};
// 用于子元素交错动画的容器
export const staggerContainer = {
hidden: { opacity: 0 },
visible: {
opacity: 1,
transition: { staggerChildren: 0.1, delayChildren: 0.2 }
}
};
// 交错容器中的单个元素
export const staggerItem = {
hidden: { opacity: 0, y: 20 },
visible: { opacity: 1, y: 0, transition: { duration: 0.5 } }
};2. Implementation Patterns
2. 实现模式
A. Scroll-triggered Animations
A. 滚动触发动画
Standard pattern for content reveals:
tsx
import { motion } from 'motion';
import { fadeInUp } from '@/lib/animations';
<motion.div
variants={fadeInUp}
initial="hidden"
whileInView="visible"
viewport={{ once: true }}
>
Content here
</motion.div>内容展示的标准模式:
tsx
import { motion } from 'motion';
import { fadeInUp } from '@/lib/animations';
<motion.div
variants={fadeInUp}
initial="hidden"
whileInView="visible"
viewport={{ once: true }}
>
内容区域
</motion.div>B. Staggered Animations
B. 交错动画
For sequential reveals of multiple elements:
tsx
import { motion } from 'motion';
import { staggerContainer, staggerItem } from '@/lib/animations';
<motion.div
variants={staggerContainer}
initial="hidden"
whileInView="visible"
viewport={{ once: true }}
>
<motion.h1 variants={staggerItem}>Title</motion.h1>
<motion.p variants={staggerItem}>Subtitle</motion.p>
<motion.div variants={staggerItem}>CTA Buttons</motion.div>
</motion.div>用于多个元素的顺序展示:
tsx
import { motion } from 'motion';
import { staggerContainer, staggerItem } from '@/lib/animations';
<motion.div
variants={staggerContainer}
initial="hidden"
whileInView="visible"
viewport={{ once: true }}
>
<motion.h1 variants={staggerItem}>标题</motion.h1>
<motion.p variants={staggerItem}>副标题</motion.p>
<motion.div variants={staggerItem}>CTA按钮</motion.div>
</motion.div>C. Interactive Animations
C. 交互式动画
For buttons and interactive elements:
tsx
import { motion } from 'motion';
<motion.button
whileHover={{ scale: 1.05 }}
whileTap={{ scale: 0.95 }}
animate={{ y: [0, -8, 0] }}
transition={{
y: { duration: 2, repeat: Infinity, ease: "easeInOut" }
}}
>
Call to Action
</motion.button>用于按钮和交互元素:
tsx
import { motion } from 'motion';
<motion.button
whileHover={{ scale: 1.05 }}
whileTap={{ scale: 0.95 }}
animate={{ y: [0, -8, 0] }}
transition={{
y: { duration: 2, repeat: Infinity, ease: "easeInOut" }
}}
>
行动召唤
</motion.button>3. Advanced Animation Features
3. 高级动画特性
A. SVG Path Animation
A. SVG路径动画
For connecting lines and decorative elements:
tsx
import { motion } from 'motion';
<motion.svg>
<motion.path
d="M 200 100 Q 400 50 600 100 T 1000 100"
stroke="rgb(var(--primary) / 0.3)"
strokeDasharray="8 8"
initial={{ pathLength: 0 }}
whileInView={{ pathLength: 1 }}
viewport={{ once: true }}
transition={{ duration: 2, delay: 0.5 }}
/>
</motion.svg>用于连接线和装饰元素:
tsx
import { motion } from 'motion';
<motion.svg>
<motion.path
d="M 200 100 Q 400 50 600 100 T 1000 100"
stroke="rgb(var(--primary) / 0.3)"
strokeDasharray="8 8"
initial={{ pathLength: 0 }}
whileInView={{ pathLength: 1 }}
viewport={{ once: true }}
transition={{ duration: 2, delay: 0.5 }}
/>
</motion.svg>B. Hover Interactions with Dynamic Properties
B. 带有动态属性的悬停交互
tsx
import { motion } from 'motion';
<motion.span
whileHover={{
scale: 1.2,
backgroundColor: "rgb(var(--primary) / 0.2)"
}}
transition={{ duration: 0.2 }}
>
Icon
</motion.span>tsx
import { motion } from 'motion';
<motion.span
whileHover={{
scale: 1.2,
backgroundColor: "rgb(var(--primary) / 0.2)"
}}
transition={{ duration: 0.2 }}
>
图标
</motion.span>4. CSS Animations for Continuous Effects
4. 用于持续效果的CSS动画
Complement Motion animations with CSS for always-running effects:
css
/* Add to globals.css */
@keyframes float {
0%, 100% { transform: translateY(0px); }
50% { transform: translateY(-5px); }
}
@keyframes slide-up {
0% { opacity: 0; transform: translateY(10px); }
100% { opacity: 1; transform: translateY(0); }
}
.animate-float {
animation: float 4s ease-in-out infinite;
}
.animate-slide-up {
animation: slide-up 0.4s ease-out forwards;
opacity: 0;
}用CSS动画补充Motion动画,实现持续运行的效果:
css
/* 添加到globals.css */
@keyframes float {
0%, 100% { transform: translateY(0px); }
50% { transform: translateY(-5px); }
}
@keyframes slide-up {
0% { opacity: 0; transform: translateY(10px); }
100% { opacity: 1; transform: translateY(0); }
}
.animate-float {
animation: float 4s ease-in-out infinite;
}
.animate-slide-up {
animation: slide-up 0.4s ease-out forwards;
opacity: 0;
}5. Animation Timing Strategy
5. 动画时序策略
Performance Optimizations
性能优化
- Use to prevent re-triggers
viewport={{ once: true }} - Consistent 0.6s duration for main elements
- 0.1s stagger delays for sequential reveals
- 0.2s delay before children start animating
- 使用 防止重复触发
viewport={{ once: true }} - 主元素统一使用0.6秒的动画时长
- 顺序展示的元素使用0.1秒的交错延迟
- 子元素动画开始前添加0.2秒的延迟
Layered Animation Approach
分层动画方案
- Immediate: CSS animations for persistent effects
- On Scroll: Motion variants for content reveals
- On Interaction: Hover/tap states for interactivity
- Background: Subtle floating animations for visual interest
- 即时效果:使用CSS动画实现持续效果
- 滚动触发:使用Motion变体实现内容展示
- 交互触发:悬停/点击状态提供交互反馈
- 背景效果:微妙的浮动动画提升视觉吸引力
6. Component Integration Examples
6. 组件集成示例
Hero Section
Hero区块
Two-column layout with opposing slide animations:
tsx
<motion.section className="grid md:grid-cols-2 gap-8">
<motion.div
variants={fadeInLeft}
initial="hidden"
whileInView="visible"
viewport={{ once: true }}
>
<h1>Hero Title</h1>
<p>Hero Description</p>
</motion.div>
<motion.div
variants={fadeInRight}
initial="hidden"
whileInView="visible"
viewport={{ once: true }}
>
<img src="/hero-image.jpg" alt="Hero" />
</motion.div>
</motion.section>双列布局,使用相反方向的滑动动画:
tsx
<motion.section className="grid md:grid-cols-2 gap-8">
<motion.div
variants={fadeInLeft}
initial="hidden"
whileInView="visible"
viewport={{ once: true }}
>
<h1>Hero标题</h1>
<p>Hero描述</p>
</motion.div>
<motion.div
variants={fadeInRight}
initial="hidden"
whileInView="visible"
viewport={{ once: true }}
>
<img src="/hero-image.jpg" alt="Hero" />
</motion.div>
</motion.section>Features Grid
功能网格
Staggered item reveals with hover interactions:
tsx
<motion.div
variants={staggerContainer}
initial="hidden"
whileInView="visible"
viewport={{ once: true }}
className="grid md:grid-cols-3 gap-6"
>
{features.map((feature, index) => (
<motion.div
key={index}
variants={staggerItem}
whileHover={{ y: -5 }}
className="p-6 bg-white rounded-lg shadow"
>
<h3>{feature.title}</h3>
<p>{feature.description}</p>
</motion.div>
))}
</motion.div>交错展示的项目,带有悬停交互:
tsx
<motion.div
variants={staggerContainer}
initial="hidden"
whileInView="visible"
viewport={{ once: true }}
className="grid md:grid-cols-3 gap-6"
>
{features.map((feature, index) => (
<motion.div
key={index}
variants={staggerItem}
whileHover={{ y: -5 }}
className="p-6 bg-white rounded-lg shadow"
>
<h3>{feature.title}</h3>
<p>{feature.description}</p>
</motion.div>
))}
</motion.div>Process Steps
流程步骤
Sequential reveals with connecting line animations:
tsx
<motion.div className="relative">
{/* Connecting line */}
<motion.div
className="absolute left-4 top-8 h-full w-0.5 bg-primary/20"
initial={{ scaleY: 0 }}
whileInView={{ scaleY: 1 }}
viewport={{ once: true }}
transition={{ duration: 1, delay: 0.5 }}
/>
{/* Steps */}
<motion.div
variants={staggerContainer}
initial="hidden"
whileInView="visible"
viewport={{ once: true }}
>
{steps.map((step, index) => (
<motion.div
key={index}
variants={staggerItem}
className="relative pl-12 pb-8"
>
<div className="absolute left-0 w-8 h-8 bg-primary rounded-full" />
<h3>{step.title}</h3>
<p>{step.description}</p>
</motion.div>
))}
</motion.div>
</motion.div>顺序展示的步骤,带有连接线动画:
tsx
<motion.div className="relative">
{/* 连接线 */}
<motion.div
className="absolute left-4 top-8 h-full w-0.5 bg-primary/20"
initial={{ scaleY: 0 }}
whileInView={{ scaleY: 1 }}
viewport={{ once: true }}
transition={{ duration: 1, delay: 0.5 }}
/>
{/* 步骤 */}
<motion.div
variants={staggerContainer}
initial="hidden"
whileInView="visible"
viewport={{ once: true }}
>
{steps.map((step, index) => (
<motion.div
key={index}
variants={staggerItem}
className="relative pl-12 pb-8"
>
<div className="absolute left-0 w-8 h-8 bg-primary rounded-full" />
<h3>{step.title}</h3>
<p>{step.description}</p>
</motion.div>
))}
</motion.div>
</motion.div>CTA Sections
CTA区块
Pulsing buttons with bounce effects:
tsx
<motion.section
variants={fadeInScale}
initial="hidden"
whileInView="visible"
viewport={{ once: true }}
className="text-center py-16"
>
<motion.button
whileHover={{ scale: 1.05 }}
whileTap={{ scale: 0.95 }}
animate={{
boxShadow: [
"0 0 0 0 rgba(59, 130, 246, 0.7)",
"0 0 0 10px rgba(59, 130, 246, 0)",
]
}}
transition={{
boxShadow: { duration: 1.5, repeat: Infinity }
}}
className="px-8 py-4 bg-blue-500 text-white rounded-lg"
>
Get Started Now
</motion.button>
</motion.section>带有脉冲效果的按钮:
tsx
<motion.section
variants={fadeInScale}
initial="hidden"
whileInView="visible"
viewport={{ once: true }}
className="text-center py-16"
>
<motion.button
whileHover={{ scale: 1.05 }}
whileTap={{ scale: 0.95 }}
animate={{
boxShadow: [
"0 0 0 0 rgba(59, 130, 246, 0.7)",
"0 0 0 10px rgba(59, 130, 246, 0)",
]
}}
transition={{
boxShadow: { duration: 1.5, repeat: Infinity }
}}
className="px-8 py-4 bg-blue-500 text-white rounded-lg"
>
立即开始
</motion.button>
</motion.section>7. Best Practices
7. 最佳实践
Performance Guidelines
性能指南
- Always use for scroll animations
viewport={{ once: true }} - Prefer and
transformchanges over layout propertiesopacity - Use sparingly and remove after animation
will-change: transform - Batch animations that occur simultaneously
- 滚动动画始终使用
viewport={{ once: true }} - 优先使用和
transform属性变化,而非布局属性opacity - 谨慎使用,动画结束后移除该属性
will-change: transform - 批量处理同时发生的动画
Accessibility Considerations
无障碍考虑
- Respect media query
prefers-reduced-motion - Provide fallbacks for users with motion sensitivity
- Keep animation durations reasonable (< 1s for most interactions)
- 尊重媒体查询
prefers-reduced-motion - 为对动效敏感的用户提供降级方案
- 保持动画时长合理(大多数交互动画时长<1秒)
Implementation Example with Reduced Motion Support
支持减少动效的实现示例
tsx
import { motion } from 'motion';
const AnimatedComponent = ({ children }) => {
const prefersReducedMotion = typeof window !== 'undefined' &&
window.matchMedia('(prefers-reduced-motion: reduce)').matches;
return (
<motion.div
variants={prefersReducedMotion ? {} : fadeInUp}
initial={prefersReducedMotion ? false : "hidden"}
whileInView={prefersReducedMotion ? false : "visible"}
viewport={{ once: true }}
>
{children}
</motion.div>
);
};tsx
import { motion } from 'motion';
const AnimatedComponent = ({ children }) => {
const prefersReducedMotion = typeof window !== 'undefined' &&
window.matchMedia('(prefers-reduced-motion: reduce)').matches;
return (
<motion.div
variants={prefersReducedMotion ? {} : fadeInUp}
initial={prefersReducedMotion ? false : "hidden"}
whileInView={prefersReducedMotion ? false : "visible"}
viewport={{ once: true }}
>
{children}
</motion.div>
);
};8. Package.json Dependencies
8. Package.json 依赖
json
{
"dependencies": {
"motion": "^12.23.26"
},
"devDependencies": {
"tw-animate-css": "^1.4.0"
}
}json
{
"dependencies": {
"motion": "^12.23.26"
},
"devDependencies": {
"tw-animate-css": "^1.4.0"
}
}Summary
总结
This animation system provides:
- Smooth, performant animations that enhance UX without overwhelming
- Clear separation between scroll-triggered reveals, interactive feedback, and ambient effects
- Centralized management for consistency across the application
- Performance optimization through proper timing and viewport controls
- Accessibility support with reduced motion preferences
The system scales from simple fade-ins to complex orchestrated sequences while maintaining optimal performance in Next.js applications.
本动画系统提供:
- 流畅、高性能的动画,提升用户体验而不造成干扰
- 清晰的职责划分,区分滚动触发展示、交互反馈和环境动效
- 集中式管理,确保应用内动画风格一致
- 性能优化,通过合理的时序和视口控制实现
- 无障碍支持,适配减少动效的用户偏好
该系统可从简单的淡入效果扩展到复杂的编排序列,同时在Next.js应用中保持最优性能。