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.divmotion.buttonmotion.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 通过 initialanimate 的状态插值实现过渡效果。例如,实现元素从左侧滑入并淡入:

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 手势交互动画

利用 whileHoverwhileTapdrag 等 props 实现交互反馈:

const GestureDemo = () => (
  
)

4.3 滚动触发动画

使用 useScrolluseTransform 实现滚动位置关联动画:

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 动画序列与时间线

使用 staggersequence 控制多元素动画顺序:

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 动态值与变换

通过 useMotionValueuseTransform 创建自定义动态值:

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 路径动画,通过 pathLengthpathOffset 控制路径绘制:

import { motion } from 'framer-motion'
const PathAnimation = () => (
  
    
  
)

6 性能优化:确保流畅体验

6.1 硬件加速与渲染优化

优先使用 transformopacity 属性动画,避免触发浏览器重排:

// 推荐:使用 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 友好:内置类型定义,提供类型安全

最佳实践

  1. 优先使用 variants 管理多状态动画,提高可维护性
  2. 避免过度动画,关键交互(如按钮、卡片)才添加动效
  3. 始终测试 “减少动画” 模式下的体验
  4. 复杂场景使用 AnimatePresence 管理组件生命周期动画

通过合理使用 Motion,开发者可以为用户界面注入生动的交互体验,同时保持代码的可维护性和性能。

posted on 2025-10-12 08:45  ycfenxi  阅读(15)  评论(0)    收藏  举报