framer-motion-magic

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Framer Motion Magic ✨

Framer Motion 魔法 ✨

Production-ready animation patterns for stunning React UIs.

可用于生产环境的动画模式,打造惊艳的React用户界面。

1. Core Concepts

1. 核心概念

motion Components

motion 组件

ElementUsage
motion.div
Animated div container
motion.button
Interactive button
motion.svg
SVG animations
motion.create(Component)
Wrap custom components
元素用途
motion.div
带动画的div容器
motion.button
交互式按钮
motion.svg
SVG动画
motion.create(Component)
包裹自定义组件

Animation Properties

动画属性

PropPurpose
initial
Starting state (string or object)
animate
Target state to animate to
exit
State when unmounting (needs AnimatePresence)
transition
Timing, easing, spring config
variants
Named animation states
属性作用
initial
初始状态(字符串或对象)
animate
动画目标状态
exit
卸载时的状态(需要AnimatePresence)
transition
时长、缓动、弹簧配置
variants
命名动画状态

Transition Types

过渡类型

TypeWhen to Use
type: "spring"
Natural, bouncy feel (default)
type: "tween"
Precise timing control
type: "inertia"
Momentum-based (drag)
tsx
// Spring (natural motion)
transition={{ type: "spring", stiffness: 300, damping: 20 }}

// Tween (precise)
transition={{ type: "tween", duration: 0.3, ease: "easeInOut" }}

类型适用场景
type: "spring"
自然弹性效果(默认)
type: "tween"
精确时长控制
type: "inertia"
基于动量的效果(拖拽)
tsx
// Spring (natural motion)
transition={{ type: "spring", stiffness: 300, damping: 20 }}

// Tween (precise)
transition={{ type: "tween", duration: 0.3, ease: "easeInOut" }}

2. Essential Patterns

2. 核心动画模式

Fade In

淡入效果

tsx
<motion.div
  initial={{ opacity: 0 }}
  animate={{ opacity: 1 }}
  transition={{ duration: 0.3 }}
>
  Content
</motion.div>
tsx
<motion.div
  initial={{ opacity: 0 }}
  animate={{ opacity: 1 }}
  transition={{ duration: 0.3 }}
>
  Content
</motion.div>

Slide Up with Fade

上滑淡入

tsx
<motion.div
  initial={{ opacity: 0, y: 20 }}
  animate={{ opacity: 1, y: 0 }}
  transition={{ duration: 0.4, ease: "easeOut" }}
>
  Content
</motion.div>
tsx
<motion.div
  initial={{ opacity: 0, y: 20 }}
  animate={{ opacity: 1, y: 0 }}
  transition={{ duration: 0.4, ease: "easeOut" }}
>
  Content
</motion.div>

Scale on Hover

悬停缩放

tsx
<motion.button
  whileHover={{ scale: 1.05 }}
  whileTap={{ scale: 0.95 }}
  transition={{ type: "spring", stiffness: 400, damping: 17 }}
>
  Click me
</motion.button>
tsx
<motion.button
  whileHover={{ scale: 1.05 }}
  whileTap={{ scale: 0.95 }}
  transition={{ type: "spring", stiffness: 400, damping: 17 }}
>
  Click me
</motion.button>

Stagger Children

子元素 stagger 动画

tsx
const containerVariants = {
  hidden: { opacity: 0 },
  visible: {
    opacity: 1,
    transition: { staggerChildren: 0.1 }
  }
};

const itemVariants = {
  hidden: { opacity: 0, y: 20 },
  visible: { opacity: 1, y: 0 }
};

<motion.ul variants={containerVariants} initial="hidden" animate="visible">
  {items.map(item => (
    <motion.li key={item.id} variants={itemVariants}>
      {item.name}
    </motion.li>
  ))}
</motion.ul>

tsx
const containerVariants = {
  hidden: { opacity: 0 },
  visible: {
    opacity: 1,
    transition: { staggerChildren: 0.1 }
  }
};

const itemVariants = {
  hidden: { opacity: 0, y: 20 },
  visible: { opacity: 1, y: 0 }
};

<motion.ul variants={containerVariants} initial="hidden" animate="visible">
  {items.map(item => (
    <motion.li key={item.id} variants={itemVariants}>
      {item.name}
    </motion.li>
  ))}
</motion.ul>

3. AnimatePresence (Mount/Unmount)

3. AnimatePresence(挂载/卸载动画)

Basic Exit Animation

基础退出动画

tsx
import { AnimatePresence, motion } from "framer-motion";

<AnimatePresence>
  {isVisible && (
    <motion.div
      key="modal"
      initial={{ opacity: 0 }}
      animate={{ opacity: 1 }}
      exit={{ opacity: 0 }}
    >
      Modal content
    </motion.div>
  )}
</AnimatePresence>
tsx
import { AnimatePresence, motion } from "framer-motion";

<AnimatePresence>
  {isVisible && (
    <motion.div
      key="modal"
      initial={{ opacity: 0 }}
      animate={{ opacity: 1 }}
      exit={{ opacity: 0 }}
    >
      Modal content
    </motion.div>
  )}
</AnimatePresence>

Mode Options

模式选项

ModeBehavior
mode="sync"
Enter/exit simultaneously (default)
mode="wait"
Wait for exit before enter
mode="popLayout"
Pop exiting element from layout flow
模式行为
mode="sync"
进入/退出同时进行(默认)
mode="wait"
等待退出完成后再进入
mode="popLayout"
将退出元素从布局流中移除

Page Transitions (Next.js)

页面过渡(Next.js)

tsx
// In _app.tsx or layout.tsx
<AnimatePresence mode="wait" initial={false}>
  <motion.div
    key={router.pathname}
    initial={{ opacity: 0, x: 20 }}
    animate={{ opacity: 1, x: 0 }}
    exit={{ opacity: 0, x: -20 }}
    transition={{ duration: 0.3 }}
  >
    <Component {...pageProps} />
  </motion.div>
</AnimatePresence>

tsx
// In _app.tsx or layout.tsx
<AnimatePresence mode="wait" initial={false}>
  <motion.div
    key={router.pathname}
    initial={{ opacity: 0, x: 20 }}
    animate={{ opacity: 1, x: 0 }}
    exit={{ opacity: 0, x: -20 }}
    transition={{ duration: 0.3 }}
  >
    <Component {...pageProps} />
  </motion.div>
</AnimatePresence>

4. Gesture Animations

4. 手势动画

Interactive Props

交互属性

PropTrigger
whileHover
Mouse enter
whileTap
Mouse down / touch
whileFocus
Element focused
whileDrag
During drag
whileInView
Element in viewport
属性触发条件
whileHover
鼠标进入
whileTap
鼠标按下/触摸
whileFocus
元素获得焦点
whileDrag
拖拽过程中
whileInView
元素进入视口

Drag

拖拽效果

tsx
<motion.div
  drag
  dragConstraints={{ left: -100, right: 100, top: -50, bottom: 50 }}
  dragElastic={0.2}
  whileDrag={{ scale: 1.1 }}
/>
tsx
<motion.div
  drag
  dragConstraints={{ left: -100, right: 100, top: -50, bottom: 50 }}
  dragElastic={0.2}
  whileDrag={{ scale: 1.1 }}
/>

Drag with useDragControls

使用useDragControls的拖拽

tsx
const controls = useDragControls();

<div onPointerDown={(e) => controls.start(e)}>
  Drag handle
</div>
<motion.div drag="x" dragControls={controls}>
  Draggable content
</motion.div>

tsx
const controls = useDragControls();

<div onPointerDown={(e) => controls.start(e)}>
  Drag handle
</div>
<motion.div drag="x" dragControls={controls}>
  Draggable content
</motion.div>

5. Scroll Animations

5. 滚动动画

whileInView (Simple)

whileInView(简易版)

tsx
<motion.div
  initial={{ opacity: 0, y: 50 }}
  whileInView={{ opacity: 1, y: 0 }}
  viewport={{ once: true, margin: "-100px" }}
  transition={{ duration: 0.5 }}
>
  Animates when scrolled into view
</motion.div>
tsx
<motion.div
  initial={{ opacity: 0, y: 50 }}
  whileInView={{ opacity: 1, y: 0 }}
  viewport={{ once: true, margin: "-100px" }}
  transition={{ duration: 0.5 }}
>
  Animates when scrolled into view
</motion.div>

useScroll Hook

useScroll 钩子

tsx
const { scrollYProgress } = useScroll();

// Animate based on scroll
<motion.div style={{ scaleX: scrollYProgress }} />
tsx
const { scrollYProgress } = useScroll();

// Animate based on scroll
<motion.div style={{ scaleX: scrollYProgress }} />

Scroll-Linked Parallax

滚动联动视差

tsx
const { scrollYProgress } = useScroll();
const y = useTransform(scrollYProgress, [0, 1], [0, -200]);

<motion.div style={{ y }}>
  Parallax content
</motion.div>

tsx
const { scrollYProgress } = useScroll();
const y = useTransform(scrollYProgress, [0, 1], [0, -200]);

<motion.div style={{ y }}>
  Parallax content
</motion.div>

6. Motion Hooks

6. 动效钩子

useMotionValue

useMotionValue

tsx
const x = useMotionValue(0);

<motion.div style={{ x }} drag="x" />
tsx
const x = useMotionValue(0);

<motion.div style={{ x }} drag="x" />

useTransform

useTransform

tsx
const x = useMotionValue(0);
const opacity = useTransform(x, [-100, 0, 100], [0, 1, 0]);
const background = useTransform(
  x,
  [-100, 0, 100],
  ["#ff0000", "#ffffff", "#00ff00"]
);
tsx
const x = useMotionValue(0);
const opacity = useTransform(x, [-100, 0, 100], [0, 1, 0]);
const background = useTransform(
  x,
  [-100, 0, 100],
  ["#ff0000", "#ffffff", "#00ff00"]
);

useSpring

useSpring

tsx
const x = useMotionValue(0);
const springX = useSpring(x, { stiffness: 300, damping: 30 });
tsx
const x = useMotionValue(0);
const springX = useSpring(x, { stiffness: 300, damping: 30 });

useVelocity

useVelocity

tsx
const x = useMotionValue(0);
const velocityX = useVelocity(x);
const scale = useTransform(velocityX, [-500, 0, 500], [0.8, 1, 0.8]);
tsx
const x = useMotionValue(0);
const velocityX = useVelocity(x);
const scale = useTransform(velocityX, [-500, 0, 500], [0.8, 1, 0.8]);

useInView

useInView

tsx
const ref = useRef(null);
const isInView = useInView(ref, { once: true });

<motion.div
  ref={ref}
  initial={{ opacity: 0 }}
  animate={isInView ? { opacity: 1 } : {}}
/>

tsx
const ref = useRef(null);
const isInView = useInView(ref, { once: true });

<motion.div
  ref={ref}
  initial={{ opacity: 0 }}
  animate={isInView ? { opacity: 1 } : {}}
/>

7. Layout Animations

7. 布局动画

Auto Layout

自动布局动画

tsx
<motion.div layout>
  {/* Size/position changes animate automatically */}
</motion.div>
tsx
<motion.div layout>
  {/* Size/position changes animate automatically */}
</motion.div>

Layout ID (Shared Element)

Layout ID(共享元素动画)

tsx
// Card in list
<motion.div layoutId={`card-${id}`}>
  <h2>{title}</h2>
</motion.div>

// Expanded card (same layoutId)
<motion.div layoutId={`card-${id}`}>
  <h2>{title}</h2>
  <p>{description}</p>
</motion.div>
tsx
// Card in list
<motion.div layoutId={`card-${id}`}>
  <h2>{title}</h2>
</motion.div>

// Expanded card (same layoutId)
<motion.div layoutId={`card-${id}`}>
  <h2>{title}</h2>
  <p>{description}</p>
</motion.div>

Layout Types

布局类型

ValueAnimates
layout
Size + position
layout="position"
Only position
layout="size"
Only size

动画范围
layout
尺寸 + 位置
layout="position"
仅位置
layout="size"
仅尺寸

8. Variants System

8. Variants 系统

Defining Variants

定义Variants

tsx
const cardVariants = {
  initial: { opacity: 0, y: 20 },
  animate: { opacity: 1, y: 0 },
  hover: { scale: 1.02, boxShadow: "0 10px 30px rgba(0,0,0,0.2)" },
  tap: { scale: 0.98 },
  exit: { opacity: 0, y: -20 }
};

<motion.div
  variants={cardVariants}
  initial="initial"
  animate="animate"
  whileHover="hover"
  whileTap="tap"
  exit="exit"
/>
tsx
const cardVariants = {
  initial: { opacity: 0, y: 20 },
  animate: { opacity: 1, y: 0 },
  hover: { scale: 1.02, boxShadow: "0 10px 30px rgba(0,0,0,0.2)" },
  tap: { scale: 0.98 },
  exit: { opacity: 0, y: -20 }
};

<motion.div
  variants={cardVariants}
  initial="initial"
  animate="animate"
  whileHover="hover"
  whileTap="tap"
  exit="exit"
/>

Orchestration

动画编排

tsx
const containerVariants = {
  hidden: {},
  visible: {
    transition: {
      staggerChildren: 0.1,
      delayChildren: 0.3
    }
  }
};

const itemVariants = {
  hidden: { opacity: 0, x: -20 },
  visible: { opacity: 1, x: 0 }
};

tsx
const containerVariants = {
  hidden: {},
  visible: {
    transition: {
      staggerChildren: 0.1,
      delayChildren: 0.3
    }
  }
};

const itemVariants = {
  hidden: { opacity: 0, x: -20 },
  visible: { opacity: 1, x: 0 }
};

9. Performance Optimization

9. 性能优化

GPU-Accelerated Properties

GPU加速属性

✅ Use❌ Avoid
transform
(x, y, scale, rotate)
width
,
height
opacity
margin
,
padding
top
,
left
,
right
,
bottom
✅ 推荐使用❌ 避免使用
transform
(x, y, scale, rotate)
width
,
height
opacity
margin
,
padding
top
,
left
,
right
,
bottom

Performance Tips

性能优化技巧

TipImplementation
Use transform over layout properties
x
,
y
instead of
left
,
top
Avoid onUpdate callbackTriggers every frame
Use layout prop sparinglyCan cause reflows
Lazy load with useInViewAnimate only when visible
Don't animate too many elementsLimit to 10-20 simultaneous
技巧实现方式
使用transform替代布局属性
x
,
y
代替
left
,
top
避免onUpdate回调会逐帧触发
谨慎使用layout属性可能导致重排
结合useInView懒加载仅在元素可见时执行动画
控制同时动画的元素数量限制在10-20个以内

Hardware Acceleration Warning

硬件加速警告

These patterns may disable GPU acceleration:
tsx
// ❌ Avoid
<motion.div onUpdate={(latest) => console.log(latest)} />
<motion.div style={{ x: motionValue }} /> // MotionValue in style
transition={{ repeatDelay: 1 }} // repeatDelay
transition={{ damping: 0 }} // Zero damping

以下模式可能会禁用GPU加速
tsx
// ❌ Avoid
<motion.div onUpdate={(latest) => console.log(latest)} />
<motion.div style={{ x: motionValue }} /> // MotionValue in style
transition={{ repeatDelay: 1 }} // repeatDelay
transition={{ damping: 0 }} // Zero damping

10. Accessibility

10. 无障碍设计

Respect Reduced Motion

尊重减少动效偏好

tsx
// Option 1: MotionConfig (Recommended)
<MotionConfig reducedMotion="user">
  <App />
</MotionConfig>

// Option 2: useReducedMotion hook
const shouldReduce = useReducedMotion();

<motion.div
  animate={shouldReduce ? { opacity: 1 } : { opacity: 1, y: 0 }}
/>
tsx
// Option 1: MotionConfig (Recommended)
<MotionConfig reducedMotion="user">
  <App />
</MotionConfig>

// Option 2: useReducedMotion hook
const shouldReduce = useReducedMotion();

<motion.div
  animate={shouldReduce ? { opacity: 1 } : { opacity: 1, y: 0 }}
/>

MotionConfig Options

MotionConfig选项

ValueBehavior
"user"
Respect OS preference
"always"
Always reduce motion
"never"
Ignore preference
行为
"user"
遵循系统偏好设置
"always"
始终减少动效
"never"
忽略偏好设置

What Gets Disabled

禁用的动效类型

When reduced motion is active:
  • opacity
    still animates
  • backgroundColor
    still animates
  • transform
    (x, y, scale, rotate) - instant
  • ❌ Layout animations - instant

当启用减少动效时:
  • opacity
    仍会执行动画
  • backgroundColor
    仍会执行动画
  • transform
    (x, y, scale, rotate) - 立即生效
  • ❌ 布局动画 - 立即生效

11. Common Patterns Reference

11. 常见模式参考

For detailed implementations with full code examples:
  • Page Transitions: See references/page-transitions.md
  • Modal/Dialog: See references/modal-patterns.md
  • List Animations: See references/list-patterns.md
  • Micro-interactions: See references/micro-interactions.md

如需完整代码示例的详细实现:
  • 页面过渡: 查看 references/page-transitions.md
  • 模态框/对话框: 查看 references/modal-patterns.md
  • 列表动画: 查看 references/list-patterns.md
  • 微交互: 查看 references/micro-interactions.md

12. Quick Reference

12. 速查手册

Easing Functions

缓动函数

NameFeel
"easeIn"
Slow start
"easeOut"
Slow end (most natural)
"easeInOut"
Slow both ends
"linear"
Constant speed
"anticipate"
Pull back then forward
"backIn"
/
"backOut"
Overshoot effect
名称效果
"easeIn"
慢启动
"easeOut"
慢结束(最自然)
"easeInOut"
两端慢
"linear"
匀速
"anticipate"
先回拉再前进
"backIn"
/
"backOut"
过冲效果

Spring Presets

弹簧预设

FeelConfig
Snappy
stiffness: 400, damping: 25
Bouncy
stiffness: 300, damping: 10
Smooth
stiffness: 100, damping: 20
Gentle
stiffness: 50, damping: 15
效果配置
轻快
stiffness: 400, damping: 25
弹跳
stiffness: 300, damping: 10
平滑
stiffness: 100, damping: 20
柔和
stiffness: 50, damping: 15

Duration Guidelines

时长指南

Animation TypeDuration
Micro-interactions100-200ms
UI feedback200-300ms
Transitions300-500ms
Page transitions400-600ms
Complex sequences500-1000ms

Remember: Animations should enhance UX, not distract. Use motion purposefully to guide attention, provide feedback, and create delight.
动画类型时长
微交互100-200ms
UI反馈200-300ms
过渡效果300-500ms
页面过渡400-600ms
复杂序列500-1000ms

记住: 动画应增强用户体验,而非分散注意力。要有目的性地使用动效,引导注意力、提供反馈并创造愉悦感。