framer-motion vs react-motion vs react-spring vs react-transition-group
React 动画库技术选型与架构对比
framer-motionreact-motionreact-springreact-transition-group类似的npm包:

React 动画库技术选型与架构对比

framer-motionreact-springreact-motionreact-transition-group 都是 React 生态中用于处理动画和过渡效果的库,但它们的实现原理和适用场景截然不同。framer-motion 主打声明式 API 和布局动画,适合大多数 UI 交互场景。react-spring 基于物理弹簧模型,适合需要精细控制物理效果的复杂交互。react-motion 是早期的物理动画库,目前已被归档不再维护。react-transition-group 是底层工具,主要用于管理 CSS 类的添加和移除,常作为其他库的依赖或用于简单的 CSS 过渡。

npm下载趋势

3 年

GitHub Stars 排名

统计详情

npm包名称
下载量
Stars
大小
Issues
发布时间
License
framer-motion032,0584.73 MB1202 天前MIT
react-motion021,929-1939 年前MIT
react-spring029,0927.23 kB891 天前MIT
react-transition-group010,246244 kB258-BSD-3-Clause

React 动画库技术选型:Framer Motion vs React Spring vs 其他

在 React 应用中实现流畅的动画效果,选择合适的库至关重要。framer-motionreact-springreact-motionreact-transition-group 代表了不同的技术路线。本文将从核心模型、代码实现、维护状态三个维度进行深度对比,帮助你在架构决策中做出正确选择。

🧠 核心动画模型:声明式 vs 物理引擎 vs CSS 类

不同的库采用了不同的驱动方式来处理动画,这直接影响了代码的编写方式和性能表现。

framer-motion 采用声明式模型。

  • 你只需定义动画的起点和终点,库会自动处理中间过程。
  • 支持布局动画(Layout Animation),能自动计算元素位置变化。
// framer-motion: 声明式动画
import { motion } from "framer-motion";

function Box() {
  return <motion.div animate={{ x: 100, opacity: 1 }} />;
}

react-spring 采用物理弹簧模型。

  • 动画基于物理参数(张力、摩擦力)而非时间曲线。
  • 通过 Hooks 暴露动画值,适合需要插值计算的场景。
// react-spring: 物理弹簧模型
import { useSpring, animated } from "@react-spring/web";

function Box() {
  const props = useSpring({ x: 100, opacity: 1 });
  return <animated.div style={props} />;
}

react-motion 采用早期的物理模型。

  • 同样基于弹簧物理,但 API 基于渲染 props 模式。
  • 已不再维护,代码模式较旧。
// react-motion: 早期物理模型 (遗留)
import { Motion, spring } from "react-motion";

function Box() {
  return (
    <Motion style={{ x: spring(100), opacity: spring(1) }}>
      {({ x, opacity }) => <div style={{ transform: `translateX(${x}px)`, opacity }} />}
    </Motion>
  );
}

react-transition-group 采用 CSS 类切换模型。

  • 它不计算动画值,只在组件进入或离开时添加/移除 CSS 类。
  • 动画逻辑完全写在 CSS 文件中。
// react-transition-group: CSS 类切换
import { CSSTransition } from "react-transition-group";

function Box({ in: show }) {
  return (
    <CSSTransition in={show} timeout={300} classNames="fade">
      <div /> {/* 动画由 .fade-enter-active 等 CSS 类控制 */}
    </CSSTransition>
  );
}

🎨 基础值动画实现对比

当我们需要改变一个元素的样式(如透明度或位置)时,各库的实现方式差异明显。

framer-motion 最简洁,直接在组件属性中定义目标值。

// framer-motion
<motion.div animate={{ opacity: 0.5, scale: 1.2 }} />

react-spring 需要先将样式对象传递给 Hook,再应用到 animated 组件。

// react-spring
const props = useSpring({ opacity: 0.5, scale: 1.2 });
<animated.div style={props} />

react-motion 需要使用渲染 props 来获取中间值,代码嵌套较深。

// react-motion
<Motion style={{ opacity: spring(0.5) }}>
  {({ opacity }) => <div style={{ opacity }} />}
</Motion>

react-transition-group 无法直接做值动画,必须依赖 CSS。

// react-transition-group
/* CSS: .fade-enter-active { opacity: 0.5; transition: opacity 300ms; } */
<CSSTransition in={true} timeout={300} classNames="fade">
  <div />
</CSSTransition>

🚪 组件挂载与卸载过渡

处理组件进入和离开 DOM 时的动画是常见需求,各库的处理机制不同。

framer-motion 使用 AnimatePresence 包裹卸载组件。

  • 即使组件从树中移除,动画也会播放完毕。
// framer-motion
import { AnimatePresence } from "framer-motion";

{show && (
  <AnimatePresence>
    <motion.div exit={{ opacity: 0 }} />
  </AnimatePresence>
)}

react-spring 通常配合 useTransition Hook 处理列表或条件渲染。

  • 返回包含样式的过渡对象,需手动映射渲染。
// react-spring
import { useTransition } from "@react-spring/web";

const transitions = useTransition(show ? [1] : [], {
  from: { opacity: 0 },
  enter: { opacity: 1 },
  leave: { opacity: 0 }
});

return transitions((style, item) => <animated.div style={style} />);

react-motion 需要手动管理状态,通常结合 TransitionMotion

  • API 较为复杂,需处理样式插值数组。
// react-motion
import { TransitionMotion } from "react-motion";

<TransitionMotion
  styles={show ? [{ key: "item", style: { opacity: 1 } }] : []}
  willEnter={() => ({ opacity: 0 })}
  willLeave={() => ({ opacity: 0 })}
>
  {interpolatedStyles => interpolatedStyles.map(({ style }) => <div style={style} />)}
</TransitionMotion>

react-transition-group 专为生命周期过渡设计,原生支持 in 属性。

  • 必须指定 timeout 以匹配 CSS 过渡时间。
// react-transition-group
<CSSTransition in={show} timeout={300} classNames="fade" unmountOnExit>
  <div />
</CSSTransition>

⚠️ 维护状态与生态健康度

选择库时,维护状态是架构决策中的关键风险因素。

framer-motion 处于活跃维护状态。

  • 社区活跃,文档完善,定期更新以支持最新 React 特性。
  • 适合长期维护的商业项目。

react-spring 处于活跃维护状态。

  • 核心团队成员稳定,专注于物理动画引擎的优化。
  • 适合对动画质量有高要求的团队。

react-motion 已正式归档(Archived)。

  • 不要在新项目中使用。GitHub 仓库已锁定,不再接受 PR 或修复。
  • 缺乏 TypeScript 支持,与现代构建工具兼容性差。

react-transition-group 处于维护模式。

  • 由 React 团队管理,变化较少,因为 API 已稳定。
  • 适合作为底层依赖,但不适合作为上层动画解决方案。

📊 总结表

特性framer-motionreact-springreact-motionreact-transition-group
动画模型声明式物理弹簧物理弹簧 (遗留)CSS 类切换
API 风格组件属性Hooks渲染 Props组件属性
布局动画✅ 原生支持❌ 需手动计算❌ 需手动计算❌ 不支持
手势支持✅ 内置拖拽/点击❌ 需配合其他库❌ 无❌ 无
维护状态🟢 活跃🟢 活跃🔴 已归档🟡 稳定维护
学习曲线

💡 最终建议

framer-motion 就像是开箱即用的动画工具箱 🧰 — 适合大多数需要快速交付、交互丰富的前端项目。它的声明式 API 能显著减少样板代码,且布局动画功能独一无二。

react-spring 就像是精密的物理引擎 ⚙️ — 适合需要高度定制物理效果或与其他状态管理深度集成的场景。如果你熟悉 Hooks 且需要细粒度控制,它是最佳选择。

react-motion 是历史遗留产物 🕸️ — 尽管它曾经很流行,但现在已不再安全。请避免在任何新代码中引入它,迁移现有项目也是明智之举。

react-transition-group 就像是底层的基础设施 🧱 — 适合简单的 CSS 过渡或作为库作者构建更高级动画组件的基石。对于普通应用开发,通常有更高效的选择。

核心结论:对于 90% 的现代 React 项目,framer-motion 是首选。只有在需要特定物理效果或极简 CSS 过渡时,才考虑 react-springreact-transition-group。务必避开 react-motion

如何选择: framer-motion vs react-motion vs react-spring vs react-transition-group

  • framer-motion:

    如果你的项目需要快速实现复杂的 UI 动画、手势交互或布局动画,请选择 framer-motion。它的声明式 API 学习成本低,且内置了性能优化,适合大多数生产环境的前端应用。

  • react-motion:

    请不要在新项目中选择 react-motion。该库已正式归档且不再维护,缺乏对现代 React 特性(如 Hooks)的支持,存在潜在的安全和兼容性风险。

  • react-spring:

    如果你需要基于物理原理的自然动画效果,或者需要通过 Hooks 对动画值进行细粒度的程序化控制,请选择 react-spring。它适合对动画曲线和物理参数有严格要求的场景。

  • react-transition-group:

    如果你只需要简单的 CSS 类切换过渡,或者正在开发一个需要极低依赖的底层组件库,请选择 react-transition-group。它不提供值动画,但能很好地管理组件的生命周期状态。

framer-motion的README

Motion logo
Motion for React

An open source animation library
for React

npm version npm downloads per month jsDelivr hits (npm) NPM License

npm install motion

Table of Contents

  1. Why Motion?
  2. 🍦 Platforms
  3. 🎓 Examples
  4. ⚡️ Motion+
  5. 👩🏻‍⚖️ License
  6. 💎 Contribute
  7. ✨ Sponsors

Why Motion?

  • Simple API: First-class React, JavaScript, and Vue packages.
  • Hybrid engine: Power of JavaScript combined with native browser APIs for 120fps, GPU-accelerated animations.
  • Production-ready: TypeScript, extensive test suite, tree-shakable, tiny footprint. Batteries included: Gestures, springs, layout transitions, scroll-linked effects, timelines.

🍦 Platforms

Motion is available for React, JavaScript and Vue.

React

import { motion } from "motion/react"

function Component() {
    return <motion.div animate={{ x: 100 }} />
}

Get started with Motion for React.

Note: Framer Motion is now Motion. Import from motion/react instead of framer-motion.

JS

import { animate } from "motion"

animate("#box", { x: 100 })

Get started with JavaScript.

Vue

<script>
    import { motion } from "motion-v"
</script>

<template> <motion.div :animate={{ x: 100 }} /> </template>

Get started with Motion for Vue.

🎓 Examples & tutorials

Browse 330+ official examples, with copy-paste code that'll level-up your animations whether you're a beginner or an expert.

Over 100 examples come with a full step-by-step tutorial.

⚡️ Motion+

A one-time payment, lifetime-updates membership:

  • 330+ examples
  • 100+ tutorials
  • Premium APIs like Cursor and Ticker
  • Transition editor for Cursor and VS Code
  • AI skills
  • Private Discord
  • Early access content

Get Motion+

👩🏻‍⚖️ License

  • Motion is MIT licensed.

💎 Contribute

✨ Sponsors

Motion is sustainable thanks to the kind support of its sponsors.

Become a sponsor

Partners

Motion powers the animations for all websites built with Framer, the web builder for creative pros. The Motion website itself is built on Framer, for its delightful canvas-based editing and powerful CMS features.

Framer

Motion drives the animations on the Cursor homepage, and is working with Cursor to bring powerful AI workflows to the Motion examples and docs.

Cursor

Platinum

Linear Figma Sanity Sanity Clerk

Gold

Silver

Liveblocks Frontend.fyi Firecrawl Puzzmo Bolt.new

Personal