1 概述:现代 React 动画解决方案
framer-motion 是一个功能强大的开源动画库,专为 React 应用设计,同时支持 Vanilla JS 和其他框架。作为目前 React 生态中最流行的动画解决方案之一,它以 简洁的 API、高性能的混合动画引擎 和 丰富的交互能力 著称,每周 npm 下载量超过 450 万次。
Motion 的核心优势在于 降低复杂动画的实现门槛:通过声明式 API,开发者无需深入掌握动画原理即可创建流畅的过渡效果、手势交互和滚动动画。其混合引擎结合了 JavaScript 动画的灵活性和浏览器原生 API(如 WAAPI)的性能优势,确保在各种设备上实现 60 FPS 动画。
核心功能 包括:
- 基础动画(淡入淡出、缩放、旋转等)
- 关键帧动画与序列控制
- 手势交互(拖拽、悬停、点击)
- 滚动触发动画
- 布局动画(自动处理元素位置变化)
- SVG 路径动画
- 3D 动画支持(通过
framer-motion-3d
包) - TypeScript 类型安全
2 安装与配置:快速上手
2.1 环境要求
Motion 12.x 要求 React 18 或更高版本;若使用 React 19,需安装 alpha 版本:
# React 18
npm install framer-motion
# React 19(实验性)
npm install framer-motion@12.0.0-alpha.0
2.2 基础配置
在 TypeScript React 项目中,直接导入 motion
组件即可使用,无需额外配置:
import { motion } from 'framer-motion/react'
const App = () => (
Hello Motion!
)
注意:对于纯客户端渲染项目,可导入 framer-motion/react-client
以优化性能:
import { motion } from 'framer-motion/react-client'
3 核心概念:动画的基本构成
3.1 motion 组件
Motion 提供了封装好的 HTML/SVG 元素(如 motion.div
、motion.button
、motion.svg
),这些组件继承了原元素的所有属性,并新增动画相关 props:
属性名 | 作用 | 示例值 |
---|---|---|
initial | 初始状态(组件挂载时) | { opacity: 0, x: -50 } |
animate | 目标状态(触发动画) | { opacity: 1, x: 0 } |
exit | 退出状态(组件卸载时) | { opacity: 0, scale: 0.8 } |
transition | 动画过渡参数 | { duration: 0.3, type: 'spring' } |
variants | 预定义动画状态集合 | { hidden: {...}, visible: {...} } |
3.2 动画状态与过渡
动画的本质是 状态变化,Motion 通过 initial
→ animate
的状态插值实现过渡效果。例如,实现元素从左侧滑入并淡入:
const SlideIn = () => (
滑入动画
)
3.3 Variants:状态化动画管理
Variants 允许将动画状态抽象为可复用的对象,便于管理复杂状态逻辑:
// 定义变体
const cardVariants = {
hidden: { opacity: 0, scale: 0.9 }, // 隐藏状态
visible: {
opacity: 1,
scale: 1,
transition: {
duration: 0.5,
staggerChildren: 0.2 // 子元素动画延迟
}
},
pressed: { scale: 0.95 } // 按压状态
}
// 使用变体
const AnimatedCard = ({ children }) => (
{children}
{/* 子元素自动继承变体状态 */}
子元素动画
)
4 常用动画示例:从基础到交互
4.1 基础属性动画
实现颜色、尺寸、旋转等 CSS 属性动画:
const PropertyAnimation = () => (
)
4.2 手势交互动画
利用 whileHover
、whileTap
、drag
等 props 实现交互反馈:
const GestureDemo = () => (
)
4.3 滚动触发动画
使用 useScroll
和 useTransform
实现滚动位置关联动画:
import { useScroll, useTransform, motion } from 'framer-motion'
const ScrollAnimation = () => {
// 获取滚动进度(0 → 1)
const { scrollYProgress } = useScroll()
// 将滚动进度转换为旋转角度(0 → 360°)
const rotate = useTransform(scrollYProgress, [0, 1], [0, 360])
return (
滚动旋转
)
}
4.4 布局动画
通过 layout
属性自动处理元素位置/尺寸变化的过渡:
import { useState } from 'react'
import { motion } from 'framer-motion'
const LayoutAnimation = () => {
const [toggle, setToggle] = useState(false)
return (
setToggle(!toggle)}
whileTap={{ scale: 0.95 }}
>
切换布局
)
}
5 高级特性:构建复杂动效
5.1 动画序列与时间线
使用 stagger
和 sequence
控制多元素动画顺序:
import { stagger, motion } from 'framer-motion'
// 定义 staggered 变体
const listVariants = {
visible: {
transition: {
staggerChildren: 0.1, // 子元素延迟 0.1s 依次动画
staggerDirection: 1 // 正向(1)或反向(-1)
}
}
}
const itemVariants = {
hidden: { opacity: 0, y: 20 },
visible: { opacity: 1, y: 0 }
}
const StaggerList = () => (
{['Item 1', 'Item 2', 'Item 3'].map((item, i) => (
{item}
))}
)
5.2 动态值与变换
通过 useMotionValue
和 useTransform
创建自定义动态值:
import { useMotionValue, useTransform, motion } from 'framer-motion'
const CustomMotionValue = () => {
// 创建动态值(初始值 0)
const x = useMotionValue(0)
// 将 x(-200 → 200)转换为旋转角度(-45° → 45°)
const rotate = useTransform(x, [-200, 200], [-45, 45])
return (
拖拽旋转
)
}
5.3 SVG 与路径动画
Motion 支持 SVG 路径动画,通过 pathLength
和 pathOffset
控制路径绘制:
import { motion } from 'framer-motion'
const PathAnimation = () => (
)
6 性能优化:确保流畅体验
6.1 硬件加速与渲染优化
优先使用 transform
和 opacity
属性动画,避免触发浏览器重排:
// 推荐:使用 transform(GPU 加速)
// 避免:直接修改 width/height(触发重排)
// 性能较差
6.2 减少不必要的动画
通过 useReducedMotion
尊重用户系统设置(如"减少动画"模式):
import { useReducedMotion } from 'framer-motion'
const ResponsiveAnimation = () => {
const shouldReduceMotion = useReducedMotion()
return (
)
}
6.3 优化变体解析
Motion 11+ 支持 延迟解析变体,提升复杂动画性能:
// 优化前:变体在组件挂载时立即解析
const variants = {
visible: { opacity: 1, x: 0 }
}
// 优化后:使用函数延迟解析(仅在动画触发时执行)
const variants = {
visible: () => ({ opacity: 1, x: 0 })
}
7 实际应用场景:从基础到复杂
7.1 导航菜单过渡
实现侧边栏菜单滑入滑出动画:
import { useState } from 'react'
import { motion, AnimatePresence } from 'framer-motion'
const Sidebar = () => {
const [isOpen, setIsOpen] = useState(false)
return (
<>
{/* AnimatePresence:监听子元素卸载动画 */}
{isOpen && (
- 首页
- 关于
- 联系
)}
)
}
7.2 数据卡片交互
结合手势和布局动画实现卡片悬停/点击效果:
const DataCard = ({ title, value }) => (
{title}
{value}
)
8 总结:Motion 的价值与最佳实践
Motion 作为现代 React 动画库,通过 声明式 API 和 高性能引擎,大幅降低了复杂动画的实现成本。核心优势包括:
- 易用性:无需深入动画原理,通过 props 快速实现动效
- 灵活性:支持从简单过渡到复杂序列的全场景动画需求
- 性能:混合引擎结合硬件加速,确保流畅体验
- TypeScript 友好:内置类型定义,提供类型安全
最佳实践:
- 优先使用
variants
管理多状态动画,提高可维护性 - 避免过度动画,关键交互(如按钮、卡片)才添加动效
- 始终测试 “减少动画” 模式下的体验
- 复杂场景使用
AnimatePresence
管理组件生命周期动画
通过合理使用 Motion,开发者可以为用户界面注入生动的交互体验,同时保持代码的可维护性和性能。