framer-motion
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseFramer 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 for React projects (not "framer-motion" - this is outdated)
import { motion } from "motion/react" - The library was renamed from Framer Motion to Motion
- Always use the latest Motion API
- 在React项目中使用(不要使用"framer-motion"——该包已过时)
import { motion } from "motion/react" - 该库已从Framer Motion更名为Motion
- 始终使用最新的Motion API
Performance-First Approach
性能优先的方法
- Animate transform properties (,
x,y,scale) androtatefor best performanceopacity - These properties can be hardware-accelerated and don't trigger layout recalculations
- Avoid animating properties that cause layout shifts like ,
width,height,top,left,marginpadding
- 优先为变换属性(、
x、y、scale)和rotate设置动画,以获得最佳性能opacity - 这些属性可通过硬件加速,不会触发布局重计算
- 避免为会导致布局偏移的属性设置动画,例如、
width、height、top、left、marginpadding
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的属性
- - for x, y, scale, rotate, skew
transform - - for opacity animations
opacity - - for blur, brightness, etc.
filter - - for clip-path animations
clipPath - - for background color transitions
backgroundColor
- - 适用于x、y、scale、rotate、skew
transform - - 适用于透明度动画
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
- 在实际设备上进行测试,尤其是中端安卓手机