framer-motion

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Framer Motion / Motion Animation Guidelines

Framer Motion / Motion 动画指南

You are an expert in Framer Motion (now Motion), React, and TypeScript. Follow these guidelines when creating animations.
您是Framer Motion(现更名为Motion)、React和TypeScript领域的专家。创建动画时请遵循以下指南。

Core Principles

核心原则

Import from the Correct Package

从正确的包导入

  • Use
    import { motion } from "motion/react"
    for React projects (not "framer-motion" - this is outdated)
  • The library was renamed from Framer Motion to Motion
  • Always use the latest Motion API
  • 在React项目中使用
    import { motion } from "motion/react"
    (不要使用"framer-motion"——该包已过时)
  • 该库已从Framer Motion更名为Motion
  • 始终使用最新的Motion API

Performance-First Approach

性能优先的方法

  • Animate transform properties (
    x
    ,
    y
    ,
    scale
    ,
    rotate
    ) and
    opacity
    for best performance
  • These properties can be hardware-accelerated and don't trigger layout recalculations
  • Avoid animating properties that cause layout shifts like
    width
    ,
    height
    ,
    top
    ,
    left
    ,
    margin
    ,
    padding
  • 优先为变换属性(
    x
    y
    scale
    rotate
    )和
    opacity
    设置动画,以获得最佳性能
  • 这些属性可通过硬件加速,不会触发布局重计算
  • 避免为会导致布局偏移的属性设置动画,例如
    width
    height
    top
    left
    margin
    padding

Hardware Acceleration

硬件加速

Use will-change Properly

正确使用will-change

tsx
// When animating transforms
<motion.div
  style={{ willChange: "transform" }}
  animate={{ x: 100, y: 50, scale: 1.2 }}
/>

// When animating other GPU-accelerated properties
<motion.div
  style={{ willChange: "opacity, transform" }}
  animate={{ opacity: 0.5, x: 100 }}
/>
tsx
// 为变换属性设置动画时
<motion.div
  style={{ willChange: "transform" }}
  animate={{ x: 100, y: 50, scale: 1.2 }}
/>

// 为其他GPU加速属性设置动画时
<motion.div
  style={{ willChange: "opacity, transform" }}
  animate={{ opacity: 0.5, x: 100 }}
/>

Properties to Add to willChange

可添加到will-change的属性

  • transform
    - for x, y, scale, rotate, skew
  • opacity
    - for opacity animations
  • filter
    - for blur, brightness, etc.
  • clipPath
    - for clip-path animations
  • backgroundColor
    - for background color transitions
  • transform
    - 适用于x、y、scale、rotate、skew
  • opacity
    - 适用于透明度动画
  • filter
    - 适用于模糊、亮度等效果
  • clipPath
    - 适用于裁剪路径动画
  • backgroundColor
    - 适用于背景色过渡

Animation Best Practices

动画最佳实践

Use Variants for Complex Animations

为复杂动画使用Variants

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

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

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

Use layoutId for Shared Element Transitions

使用layoutId实现共享元素过渡

tsx
<motion.div layoutId="shared-element" />
tsx
<motion.div layoutId="shared-element" />

Prefer spring Animations

优先使用spring动画

tsx
// Springs feel more natural than duration-based animations
<motion.div
  animate={{ x: 100 }}
  transition={{ type: "spring", stiffness: 300, damping: 30 }}
/>
tsx
// 弹簧动画比基于时长的动画更自然
<motion.div
  animate={{ x: 100 }}
  transition={{ type: "spring", stiffness: 300, damping: 30 }}
/>

React Integration

React集成

Memoization for Performance

利用Memoization提升性能

tsx
// Memoize animation variants
const variants = useMemo(() => ({
  hidden: { opacity: 0 },
  visible: { opacity: 1 }
}), []);

// Memoize callbacks
const handleAnimationComplete = useCallback(() => {
  // handler logic
}, []);
tsx
// 对动画Variants进行记忆化处理
const variants = useMemo(() => ({
  hidden: { opacity: 0 },
  visible: { opacity: 1 }
}), []);

// 对回调函数进行记忆化处理
const handleAnimationComplete = useCallback(() => {
  // 处理逻辑
}, []);

Avoid Inline Style Objects

避免内联样式对象

tsx
// Bad - creates new object on every render
<motion.div style={{ willChange: "transform" }} />

// Good - define outside or memoize
const style = { willChange: "transform" };
<motion.div style={style} />
tsx
// 不良实践 - 每次渲染都会创建新对象
<motion.div style={{ willChange: "transform" }} />

// 良好实践 - 在外部定义或进行记忆化处理
const style = { willChange: "transform" };
<motion.div style={style} />

Accessibility

无障碍适配

Respect Reduced Motion Preferences

尊重减少动画的偏好设置

tsx
import { useReducedMotion } from "motion/react";

function Component() {
  const shouldReduceMotion = useReducedMotion();

  return (
    <motion.div
      animate={{ x: shouldReduceMotion ? 0 : 100 }}
      transition={{ duration: shouldReduceMotion ? 0 : 0.3 }}
    />
  );
}
tsx
import { useReducedMotion } from "motion/react";

function Component() {
  const shouldReduceMotion = useReducedMotion();

  return (
    <motion.div
      animate={{ x: shouldReduceMotion ? 0 : 100 }}
      transition={{ duration: shouldReduceMotion ? 0 : 0.3 }}
    />
  );
}

Gesture Animations

手势动画

Use Gesture Props Correctly

正确使用手势属性

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

Scroll Animations

滚动动画

Use useScroll for Scroll-Linked Animations

使用useScroll实现滚动关联动画

tsx
import { useScroll, useTransform, motion } from "motion/react";

function ParallaxComponent() {
  const { scrollYProgress } = useScroll();
  const y = useTransform(scrollYProgress, [0, 1], [0, -100]);

  return <motion.div style={{ y }} />;
}
tsx
import { useScroll, useTransform, motion } from "motion/react";

function ParallaxComponent() {
  const { scrollYProgress } = useScroll();
  const y = useTransform(scrollYProgress, [0, 1], [0, -100]);

  return <motion.div style={{ y }} />;
}

Exit Animations

退出动画

Use AnimatePresence for Exit Animations

使用AnimatePresence实现退出动画

tsx
import { AnimatePresence, motion } from "motion/react";

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

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

Common Patterns

常见模式

Staggered List Animation

交错列表动画

tsx
<motion.ul
  initial="hidden"
  animate="visible"
  variants={{
    visible: { transition: { staggerChildren: 0.07 } }
  }}
>
  {items.map((item) => (
    <motion.li
      key={item.id}
      variants={{
        hidden: { opacity: 0, y: 20 },
        visible: { opacity: 1, y: 0 }
      }}
    />
  ))}
</motion.ul>
tsx
<motion.ul
  initial="hidden"
  animate="visible"
  variants={{
    visible: { transition: { staggerChildren: 0.07 } }
  }}
>
  {items.map((item) => (
    <motion.li
      key={item.id}
      variants={{
        hidden: { opacity: 0, y: 20 },
        visible: { opacity: 1, y: 0 }
      }}
    />
  ))}
</motion.ul>

Page Transitions

页面过渡

tsx
const pageTransition = {
  initial: { opacity: 0, x: -20 },
  animate: { opacity: 1, x: 0 },
  exit: { opacity: 0, x: 20 },
  transition: { duration: 0.3 }
};
tsx
const pageTransition = {
  initial: { opacity: 0, x: -20 },
  animate: { opacity: 1, x: 0 },
  exit: { opacity: 0, x: 20 },
  transition: { duration: 0.3 }
};

Performance Debugging

性能调试

  • Use React DevTools to inspect re-renders
  • Use Chrome DevTools Performance tab to identify animation jank
  • Target 60fps minimum, 120fps on high refresh rate displays
  • Test on actual devices, especially mid-range Android phones
  • 使用React DevTools检查重渲染情况
  • 使用Chrome DevTools的性能面板识别动画卡顿问题
  • 目标最低帧率为60fps,高刷新率显示器上为120fps
  • 在实际设备上进行测试,尤其是中端安卓手机