🤩React动画新宠儿:framer-motion从入门到精通

135 阅读24分钟

一、引言

image.png

你是否曾被网页上那些炫酷的动画效果所吸引?比如,当你点击一个按钮,页面元素像被施了魔法一样,平滑地滑动、渐变、缩放,仿佛它们有了生命。这些有趣的动画场景不仅让网页变得生动活泼,还能极大地提升用户体验。在前端开发中,动画就像是给网页注入的一剂 “活力针”,能让原本单调的页面瞬间变得魅力四射。

在众多实现动画的方式中,CSS transition 是我们常用的基础手段,它可以轻松实现一些简单的样式过渡,比如元素的颜色、大小、位置变化等。然而,当我们面对复杂的动画需求,如物理效果、手势交互、复杂的动画序列时,CSS transition 就显得有些力不从心了。这时候,我们就需要借助一些强大的第三方动画库,而 framer - motion 就是其中的佼佼者!它就像是一位无所不能的动画大师,能帮我们实现各种超乎想象的动画效果,让我们的网页应用脱颖而出。接下来,就让我们一起走进 framer - motion 的奇妙世界吧!

屏幕录制 2025-07-22 202229.gif

二、Framer - Motion 是什么

image.png

Framer - Motion 是 React 生态系统中一颗璀璨的明星✨,深受广大开发者的喜爱。它就像是一个万能的动画魔法师,为 React 应用带来了前所未有的动画体验。凭借其强大的功能和简洁易用的 API,在众多动画库中脱颖而出,成为实现复杂动画效果和交互的首选工具。 image.png

它提供了一种声明式的动画方式,让我们可以像描述物体的行为一样,轻松地定义动画的起始、结束状态以及过渡效果。这意味着我们不需要再像使用传统 CSS 动画那样,手动计算每一帧的状态,也不用编写大量繁琐的 JavaScript 代码来操作 DOM 实现动画效果。Framer - Motion 会自动帮我们处理这些复杂的细节,让动画开发变得更加高效和有趣😎。

比如,在一个电商应用中,当用户将商品添加到购物车时,我们可以使用 Framer - Motion 让商品图标以一个漂亮的动画效果飞入购物车图标中,给用户带来更加直观和有趣的交互体验;又或者在一个数据可视化项目中,当数据发生变化时,使用 Framer - Motion 让图表元素以平滑的动画过渡来展示数据的变化,使数据的呈现更加生动和易于理解。它适用于各种需要动画效果的场景,无论是简单的 UI 组件动画,还是复杂的交互界面动画,Framer - Motion 都能轻松应对,为我们的应用增添独特的魅力。

三、快速上手

(一)安装

要在 React 项目中使用 framer - motion,安装过程非常简单,就像从魔法口袋里掏出工具一样轻松😎。如果你使用的是 npm,只需在项目的终端中输入以下命令:

npm install framer-motion

如果你更喜欢 yarn,也没问题,使用下面的命令即可:

yarn add framer-motion

安装完成后,就可以在项目中引入这个神奇的动画库,开启我们的动画之旅啦!🚀

(二)基本用法

安装好 framer - motion 后,就可以开始体验它的强大功能了。它的核心组件是 motion,通过将普通的 HTML 元素(如 div、span 等)替换为 motion.div、motion.span 等,就能为这些元素赋予动画能力,就像给它们披上了一件魔法披风🧙‍♂️。

接下来,我们以一个简单的元素淡入动画为例,来看看它的基本用法。先看下面这段代码:

import React from 'react';
import { motion } from 'framer-motion';
const FadeInComponent = () => {
  return (
    <motion.div
      initial={{ opacity: 0 }}
      animate={{ opacity: 1 }}
      transition={{ duration: 0.5 }}
      style={{
        backgroundColor: 'lightgreen',
        padding: 20,
        borderRadius: 5,
        color: 'white',
        fontSize: '1.2rem',
        textAlign: 'center'
      }}
    >
      我是淡入动画的内容,快来看看我是怎么出现的吧~
    </motion.div>
  );
};
export default FadeInComponent;

在这段代码中,我们创建了一个 FadeInComponent 组件,其中使用了 motion.div 来包裹一段文本。这里面的 initial、animate 和 transition 属性是实现动画的关键,它们就像是动画的三个小精灵🧚‍♀️,各司其职:

  • initial:这个属性定义了元素的初始状态,就像一场演出开始前演员的准备姿势。在我们的例子中,initial={{ opacity: 0 }} 表示元素初始时的透明度为 0,也就是完全透明,看不见的状态😉。
  • animate:它定义了元素的动画状态,当组件渲染后,元素会从 initial 状态过渡到 animate 状态,就像演员在舞台上开始表演啦🎭。这里 animate={{ opacity: 1 }} 表示元素最终的透明度会变为 1,也就是完全不透明,出现在我们眼前。
  • transition:这个属性用于设置动画过渡的参数,比如动画的持续时间、缓动函数等,它决定了动画的 “节奏”。transition={{ duration: 0.5 }} 表示动画的持续时间为 0.5 秒,在这 0.5 秒内,元素会从初始的透明状态平滑地过渡到完全不透明的状态,给我们呈现出一个淡入的动画效果,是不是很神奇😜?

通过这个简单的例子,我们可以看到,使用 framer - motion 实现动画就是这么简单直观,只需要通过这几个属性,就能轻松控制元素的动画状态,让网页变得生动起来。接下来,我们还会深入探讨更多有趣的用法和高级特性,让你的动画技能更上一层楼💪!

四、核心属性详解

(一)initial:初始状态大揭秘

image.png

initial 属性就像是动画之旅的起点,它定义了元素在动画开始前的初始状态。通过设置不同的属性值,我们可以让元素在初始时呈现出各种各样的状态,比如位置、透明度、缩放等,就像为一场魔法表演准备好独特的开场姿势🎩。

来看下面这个例子,我们让一个 div 元素在初始时位于页面左上角,并且透明度为 0.5,大小缩放为 0.8 倍:

import React from'react';
import { motion } from 'framer-motion';
const InitialExample = () => {
  return (
    <motion.div
      initial={{ x: 0, y: 0, opacity: 0.5, scale: 0.8 }}
      animate={{ x: 200, y: 200, opacity: 1, scale: 1 }}
      transition={{ duration: 1 }}
      style={{
        backgroundColor: 'orange',
        width: 100,
        height: 100,
        borderRadius: 5
      }}
    />
  );
};
export default InitialExample;

在这段代码中,initial 属性的值是一个对象,其中 x 和 y 分别表示元素在水平和垂直方向上的位置,opacity 表示透明度,scale 表示缩放比例。这样,当页面加载时,这个 div 元素就会以我们设定的初始状态出现在页面上,然后再开始执行动画,是不是很有趣😉?通过巧妙地设置 initial 属性,我们可以为动画创造出丰富多样的起始条件,为后续的动画效果打下基础。

(二)animate:动画效果全掌控

image.png

animate 属性是动画的核心部分,它决定了元素最终要达到的目标状态,就像魔法咒语一样,让元素按照我们的意愿进行各种神奇的变化,实现各种炫酷的动画效果,比如移动、旋转、变色等等,是动画的 “表演时刻”🎭。

下面是一个综合展示多种动画效果的示例,让元素在动画过程中实现位置移动、旋转、颜色变化和缩放:

import React from'react';
import { motion } from 'framer-motion';
const AnimateExample = () => {
  return (
    <motion.div
      initial={{ x: 0, y: 0, rotate: 0, backgroundColor: 'green', scale: 1 }}
      animate={{ x: 300, y: 300, rotate: 360, backgroundColor:'red', scale: 1.5 }}
      transition={{ duration: 2 }}
      style={{
        width: 100,
        height: 100,
        borderRadius: 5
      }}
    />
  );
};
export default AnimateExample;

在这个例子中,animate 属性设置的对象里,x 和 y 的变化使元素从初始位置移动到了坐标 (300, 300) 的位置;rotate 从 0 变为 360,让元素顺时针旋转了一圈;backgroundColor 从 green 变为 red,实现了颜色的切换;scale 从 1 变为 1.5,使元素放大了 1.5 倍。这些属性的变化组合在一起,为我们呈现出了一个非常丰富的动画效果,元素就像一个灵动的舞者,在页面上尽情展示着各种精彩的动作💃🕺。通过 animate 属性,我们可以充分发挥想象力,创造出各种各样令人惊叹的动画效果,为用户带来更加生动和有趣的交互体验。

(三)transition:过渡效果巧调节

image.png

transition 属性是动画过渡的 “节奏大师”,它负责控制动画从初始状态到目标状态的过渡过程,其中的 duration(持续时间)和 ease(缓动函数)等参数起着关键作用,不同的参数值会让动画的过渡效果截然不同,就像音乐中的节奏和旋律,决定了动画的 “风格”🎶。

duration 决定了动画持续的时间,单位是秒。比如 duration: 0.5 表示动画会在 0.5 秒内完成过渡,时间越短,动画就越快速;时间越长,动画就越缓慢、越流畅。我们可以通过调整这个值来控制动画的快慢节奏,以适应不同的场景需求。

ease 是缓动函数,它决定了动画在过渡过程中的速度变化方式,有很多种不同的取值,每种取值都会带来独特的动画感觉:

  • easeIn:动画开始时速度较慢,然后逐渐加快,就像汽车启动时慢慢加速🚗。
  • easeOut:与 easeIn 相反,动画开始时速度较快,然后逐渐减慢,就像汽车快要停车时慢慢减速。
  • easeInOut:动画开始和结束时速度较慢,中间速度较快,这种方式最为常用,它能让动画看起来更加平滑自然,就像我们日常走路时的步伐,有一个自然的加速和减速过程👣。
  • linear:动画在整个过渡过程中保持匀速,没有明显的加速或减速,就像在平坦道路上匀速行驶的火车🚂。

下面通过一个示例来展示不同 ease 值下的动画效果:

import React from'react';
import { motion } from 'framer-motion';
const TransitionExample = () => {
  return (
    <div>
      <motion.div
        initial={{ x: 0 }}
        animate={{ x: 200 }}
        transition={{ duration: 1, ease: 'easeIn' }}
        style={{
          backgroundColor: 'lightblue',
          width: 50,
          height: 50,
          borderRadius: 5,
          marginBottom: 10
        }}
      />
      <motion.div
        initial={{ x: 0 }}
        animate={{ x: 200 }}
        transition={{ duration: 1, ease: 'easeOut' }}
        style={{
          backgroundColor: 'lightgreen',
          width: 50,
          height: 50,
          borderRadius: 5,
          marginBottom: 10
        }}
      />
      <motion.div
        initial={{ x: 0 }}
        animate={{ x: 200 }}
        transition={{ duration: 1, ease: 'easeInOut' }}
        style={{
          backgroundColor: 'pink',
          width: 50,
          height: 50,
          borderRadius: 5,
          marginBottom: 10
        }}
      />
      <motion.div
        initial={{ x: 0 }}
        animate={{ x: 200 }}
        transition={{ duration: 1, ease: 'linear' }}
        style={{
          backgroundColor: 'yellow',
          width: 50,
          height: 50,
          borderRadius: 5
        }}
      />
    </div>
  );
};
export default TransitionExample;

在这个示例中,我们创建了四个相同的 div 元素,它们都从 x 为 0 的位置移动到 x 为 200 的位置,持续时间都是 1 秒,但 ease 值分别设置为 easeIn、easeOut、easeInOut 和 linear。当页面加载后,你可以清楚地看到这四个 div 元素在移动过程中的速度变化差异,从而更好地理解不同缓动函数对动画过渡效果的影响。通过合理地选择 duration 和 ease 参数,我们可以精确地控制动画的过渡效果,让动画更加贴合我们的设计需求,为用户带来更加舒适和自然的视觉体验。

五、进阶特性探索

image.png

(一)Variants:状态管理大师

随着对 framer - motion 的深入使用,我们会遇到一些需要管理多个动画状态的复杂场景,这时候 Variants 就像是一位贴心的状态管理大师,前来拯救我们于 “混乱” 之中😎。Variants 允许我们定义一组动画状态,然后在不同的状态之间轻松切换,让动画的管理变得更加清晰和高效。

以一个常见的折叠菜单为例,我们来看看 Variants 的强大之处。在这个折叠菜单中,菜单有展开和收起两个状态,每个状态下菜单的高度、透明度和位置都有不同的表现。代码如下:

import React, { useState } from'react';
import { motion } from 'framer-motion';
const menuVariants = {
  collapsed: {
    height: 0,
    opacity: 0,
    y: -10,
    transition: {
      duration: 0.3,
      ease: 'easeOut'
    }
  },
  expanded: {
    height: 200,
    opacity: 1,
    y: 0,
    transition: {
      duration: 0.5,
      ease: 'easeInOut'
    }
  }
};
const CollapsibleMenu = () => {
  const [isOpen, setIsOpen] = useState(false);
  return (
    <div>
      <button onClick={() => setIsOpen(!isOpen)}>
        {isOpen? 'Close Menu' : 'Open Menu'}
      </button>
      <motion.div
        variants={menuVariants}
        initial={isOpen? 'expanded' : 'collapsed'}
        animate={isOpen? 'expanded' : 'collapsed'}
        style={{
          backgroundColor: 'lightgray',
          width: 200,
          borderRadius: 5,
          overflow: 'hidden',
          marginTop: 10
        }}
      >
        <ul style={{ listStyleType: 'none', padding: 0 }}>
          <li style={{ padding: 5 }}>Item 1</li>
          <li style={{ padding: 5 }}>Item 2</li>
          <li style={{ padding: 5 }}>Item 3</li>
        </ul>
      </motion.div>
    </div>
  );
};
export default CollapsibleMenu;

在这段代码中,我们首先定义了一个 menuVariants 对象,它包含了两个状态:collapsed(收起)和 expanded(展开)。每个状态都有对应的动画属性设置,包括高度、透明度、位置以及过渡效果。然后在 CollapsibleMenu 组件中,通过 useState 来管理菜单的打开和关闭状态,再利用 variants 属性将定义好的状态集合应用到 motion.div 上,通过 initial 和 animate 属性根据当前的 isOpen 状态来切换菜单的动画状态。这样,当用户点击按钮时,菜单就能以流畅的动画效果展开或收起,是不是感觉代码逻辑变得更加清晰了呢🧐?通过 Variants,我们可以轻松应对各种复杂的动画状态管理需求,为用户带来更加流畅和自然的交互体验。

(二)事件处理:动画交互随心控

动画不仅仅是为了展示炫酷的效果,更重要的是能够与用户进行交互,增强用户体验。framer - motion 提供了丰富的事件处理属性,让我们可以轻松实现动画与用户交互的结合,就像给动画赋予了与用户交流的 “语言”,让它们能够根据用户的操作做出相应的反应😃。

其中,onAnimationComplete 是一个非常常用的事件处理属性,它可以在动画完成时触发一个回调函数,让我们可以在动画结束后执行一些特定的操作。比如,当一个元素的淡入动画完成后,我们可以显示一个提示信息,或者触发另一个动画。下面是一个简单的示例:

import React from'react';
import { motion } from 'framer-motion';
const AnimationWithEvent = () => {
  const handleAnimationComplete = () => {
    alert('动画已经完成啦!');
  };
  return (
    <motion.div
      initial={{ opacity: 0 }}
      animate={{ opacity: 1 }}
      transition={{ duration: 1 }}
      onAnimationComplete={handleAnimationComplete}
      style={{
        backgroundColor: 'lightblue',
        padding: 20,
        borderRadius: 5,
        color: 'white',
        fontSize: '1.2rem',
        textAlign: 'center'
      }}
    >
      我是带有事件处理的动画,等我出现后会有惊喜哦~
    </motion.div>
  );
};
export default AnimationWithEvent;

在这个例子中,我们定义了一个 handleAnimationComplete 函数,当 motion.div 的淡入动画完成时,onAnimationComplete 属性会触发这个函数,从而弹出一个提示框,告诉用户动画已经完成。这只是 onAnimationComplete 的一个简单应用,在实际项目中,我们可以根据具体需求,在这个回调函数中执行更复杂的操作,比如更新数据、切换页面状态等等。除了 onAnimationComplete,framer - motion 还提供了其他一些事件处理属性,如 onClick(点击事件)、onHoverStart(鼠标悬停开始事件)、onHoverEnd(鼠标悬停结束事件)等,这些属性可以让我们实现更加丰富多样的交互效果,比如点击按钮触发动画、鼠标悬停时元素发生动画变化等等,让我们的网页应用更加生动有趣,与用户的互动更加紧密🤝。

(三)复杂动画制作:创意动画随心造

前面我们已经了解了如何使用 framer - motion 实现一些基本的动画效果,但是在实际的项目中,我们常常需要制作更加复杂、富有创意的动画,来吸引用户的注意力,提升用户体验。这时候,framer - motion 的强大之处就再次体现出来啦,它允许我们将多个动画属性组合在一起,就像一个动画艺术家将各种绘画元素组合成一幅绚丽的画作一样,创造出令人惊叹的复杂动画效果😎。

比如,我们想要让一个元素同时进行旋转、平移和缩放的动画,就像一个在空中飞舞的魔法球,是不是很炫酷呢🧙‍♂️?下面是实现这个效果的代码示例:

import React from'react';
import { motion } from 'framer-motion';
const ComplexAnimation = () => {
  return (
    <motion.div
      initial={{ rotate: 0, x: 0, y: 0, scale: 1 }}
      animate={{ rotate: 360, x: 200, y: 200, scale: 1.5 }}
      transition={{ duration: 2, ease: 'easeInOut' }}
      style={{
        backgroundColor: 'purple',
        width: 100,
        height: 100,
        borderRadius: 50,
        color: 'white',
        fontSize: '1.2rem',
        textAlign: 'center',
        display: 'flex',
        justifyContent: 'center',
        alignItems: 'center'
      }}
    >
      我是一个正在施展魔法的小球~
    </motion.div>
  );
};
export default ComplexAnimation;

在这段代码中,initial 属性定义了元素的初始状态,animate 属性则定义了动画结束时的状态,我们在其中同时设置了 rotate(旋转)、x 和 y(平移)以及 scale(缩放)这几个动画属性,并且通过 transition 属性设置了动画的持续时间和缓动函数。当页面加载后,这个 div 元素就会像一个充满魔力的小球一样,在 2 秒内从初始位置开始,一边旋转 360 度,一边平移到坐标 (200, 200) 的位置,同时放大到原来的 1.5 倍,是不是感觉很神奇😜?通过这种方式,我们可以充分发挥自己的想象力,将各种动画属性进行组合,创造出独一无二的动画效果,为用户带来全新的视觉体验。无论是制作一个充满活力的游戏界面,还是一个富有创意的产品展示页面,framer - motion 都能满足我们对复杂动画的需求,让我们的创意得以尽情展现💪。

(四)响应式动画:适配不同屏幕的魔法

在当今这个多设备的时代,我们的网页应用需要能够在各种不同尺寸的屏幕上完美展示,这就要求我们的动画也具备响应式的能力,能够根据屏幕尺寸或用户操作自动调整动画效果,就像一个神奇的魔法师,能够根据环境的变化施展不同的魔法🧙‍♀️。framer - motion 结合 React 的状态管理,为我们提供了实现响应式动画的强大功能。

下面我们通过一个示例来演示如何根据屏幕尺寸切换动画效果。假设我们有一个元素,在大屏幕上它以平移的方式进入页面,而在小屏幕上则以缩放的方式进入页面。代码如下:

import React, { useState, useEffect } from'react';
import { motion } from 'framer-motion';
const ResponsiveAnimation = () => {
  const [isLargeScreen, setIsLargeScreen] = useState(window.innerWidth > 768);
  useEffect(() => {
    const handleResize = () => {
      setIsLargeScreen(window.innerWidth > 768);
    };
    window.addEventListener('resize', handleResize);
    return () => {
      window.removeEventListener('resize', handleResize);
    };
  }, []);
  const largeScreenVariants = {
    initial: { x: -100, opacity: 0 },
    animate: { x: 0, opacity: 1 },
    transition: { duration: 0.5, ease: 'easeInOut' }
  };
  const smallScreenVariants = {
    initial: { scale: 0, opacity: 0 },
    animate: { scale: 1, opacity: 1 },
    transition: { duration: 0.5, ease: 'easeInOut' }
  };
  return (
    <div>
      <motion.div
        variants={isLargeScreen? largeScreenVariants : smallScreenVariants}
        initial="initial"
        animate="animate"
        style={{
          backgroundColor: 'orange',
          width: 100,
          height: 100,
          borderRadius: 5,
          color: 'white',
          fontSize: '1.2rem',
          textAlign: 'center',
          display: 'flex',
          justifyContent: 'center',
          alignItems: 'center'
        }}
      >
        我会根据屏幕大小施展不同的动画魔法哦~
      </motion.div>
    </div>
  );
};
export default ResponsiveAnimation;

在这段代码中,我们首先使用 useState 和 useEffect 来监听窗口大小的变化,根据屏幕宽度是否大于 768px 来设置 isLargeScreen 的状态。然后分别定义了 largeScreenVariants 和 smallScreenVariants 两个动画状态集合,对应大屏幕和小屏幕的动画效果。最后,在 motion.div 中,通过 variants 属性根据 isLargeScreen 的值来选择对应的动画状态集合,从而实现根据屏幕尺寸切换动画效果的功能。当我们在不同尺寸的屏幕上打开这个页面时,就会看到元素以不同的动画方式进入页面,是不是很有趣呢😉?除了根据屏幕尺寸,我们还可以结合用户的其他操作,如点击、滑动等,来实现更加丰富的响应式动画效果,让我们的网页应用在不同的场景下都能给用户带来最佳的体验。

六、与 CSS transition 对比

image.png

在前端动画的世界里,CSS transition 是我们的老朋友了,它就像一位基本功扎实的舞者,能够轻松完成一些简单而优雅的动作;而 framer - motion 则像是一位技艺精湛的全能艺术家,不仅能完美演绎复杂的舞蹈动作,还能带来各种令人惊叹的创意表演。下面我们就以高度展开 / 收起动画为例,来看看它们各自的表现,以及在不同方面的优缺点,帮助大家在实际项目中根据需求做出明智的选择。

屏幕录制 2025-07-22 202229.gif

(一)CSS transition 实现动画示例

先来看使用 CSS transition 实现高度展开 / 收起动画的代码示例:

// Box.jsx
import { useState } from "react";
import styles from "./box.module.css";
const Box = () => {
  const [isOpen, setIsOpen] = useState(false);
  return (
    <div>
      <button onClick={() => setIsOpen(!isOpen)}>
        {isOpen? "Close" : "Open"}
      </button>
      <div className={`${styles.box} ${isOpen? styles.open : ""}`}></div>
    </div>
  );
};
export default Box;
/* box.module.css */
.box {
  width: 100px;
  height: 0;
  background-color: lightblue;
  transition: height 0.3s ease-in-out;
  overflow: hidden;
}
.box.open {
  height: 100px;
}

在这段代码中,我们通过 useState 来管理 isOpen 状态,当点击按钮时,isOpen 的值会切换。在 CSS 中,通过 transition 属性为 height 的变化添加了过渡效果,持续时间为 0.3 秒,缓动函数为 ease-in-out。当 isOpen 为 true 时,添加 open 类,元素的高度从 0 平滑过渡到 100px,实现展开效果;当 isOpen 为 false 时,移除 open 类,高度从 100px 平滑过渡到 0,实现收起效果。整个过程就像是窗帘的拉开和关闭,简单而直接。

(二)Framer - motion 实现相同动画示例

接下来,看看用 framer - motion 实现相同动画的代码:

// MotionBox.jsx
import { useState } from "react";
import { motion } from "framer-motion";
import styles from "./motionbox.module.css";
const MotionBox = () => {
  const [isOpen, setIsOpen] = useState(false);
  return (
    <div>
      <button onClick={() => setIsOpen(!isOpen)}>
        {isOpen? "Close" : "Open"}
      </button>
      <motion.div
        className={`${styles.motionbox} ${isOpen? styles.open : ""}`}
        initial={{ height: 0, opacity: 0 }}
        animate={
          isOpen
           ? { height: 120, opacity: 1 }
            : { height: 0, opacity: 0 }
        }
        transition={{ duration: 0.5, ease: "easeInOut" }}
      >
        <h1 className={styles.title}>Love❤️Xiang</h1>
      </motion.div>
    </div>
  );
};
export default MotionBox;

这里使用 motion.div 来包裹元素,通过 initial 属性设置初始状态为高度 0 且透明度 0,即完全隐藏;animate 属性根据 isOpen 的值来动态设置目标状态,当 isOpen 为 true 时,高度变为 120px 且透明度变为 1,实现展开并显示内容的效果,反之则收起并隐藏;transition 属性设置动画的持续时间为 0.5 秒,缓动函数为 easeInOut。可以看到,framer - motion 以一种声明式的方式来描述动画的状态变化,就像是在写一个动画剧本,每个场景都清晰明了。

(三)对比分析

从上面的示例可以看出,CSS transition 和 framer - motion 在实现动画上有各自的特点,我们从以下几个方面来详细对比一下:

  • 代码复杂度
    • CSS transition:相对简单,主要通过 CSS 类名的切换来触发动画,适合简单的动画场景。就像搭建一个简单的积木塔,几块积木就能完成,代码量较少,逻辑也比较直观。
    • Framer - motion:稍复杂一些,需要使用特定的属性(如 initial、animate、transition 等)来定义动画的各个状态和过渡效果。但这种声明式的方式在处理复杂动画时,能让代码结构更清晰,就像搭建一个复杂的乐高模型,虽然零件多,但每个零件的作用明确,组装起来有条不紊。
  • 动画能力
    • CSS transition:仅支持有限的 CSS 属性过渡,如 width、height、opacity、color 等常见属性的简单变化,对于一些复杂的动画效果,如物理模拟、复杂的动画序列等,就难以实现,就像一个只会跳简单舞蹈动作的舞者,无法完成高难度的舞蹈表演。
    • Framer - motion:支持更多的动画属性,包括各种 CSS 变形属性(如 transform 中的 rotate、scale、translate 等),还能实现物理效果(如弹簧效果、重力效果等)、复杂的动画序列以及多个元素之间的动画协同,就像一位全能的舞者,能轻松驾驭各种复杂的舞蹈动作,还能与其他舞者配合完成精彩的群舞表演。
  • 交互性
    • CSS transition:交互性相对较弱,主要通过 CSS 的伪类(如 :hover、:active 等)和 JavaScript 切换类名来实现简单的交互,无法实现像手势交互、拖拽等复杂的交互效果,就像一个只能与观众进行简单眼神交流的演员,互动方式有限。
    • Framer - motion:内置了强大的手势识别系统,支持 hover、tap、pan(拖拽)、drag(拖动)等多种交互方式,并且可以轻松实现动画与交互的联动,比如实现可拖拽的元素、点击后展开的菜单并伴有动画效果等,就像一个能与观众进行全方位互动的演员,能根据观众的反应做出各种精彩的表演。
  • 维护性
    • CSS transition:在简单动画场景下,维护性较好,因为代码简单易懂。但当动画需求变得复杂时,可能需要大量的 CSS 类名和复杂的选择器,这会使代码的维护难度增加,就像一个简单的小房子,维护起来很容易,但如果不断添加各种功能和装饰,就会变得难以管理。
    • Framer - motion:采用声明式的写法,动画逻辑集中在组件内部,结构清晰,易于理解和维护。即使动画变得复杂,通过合理地组织 variants 和事件处理函数,也能保持代码的可读性和可维护性,就像一个设计合理的大型建筑,各个功能区域划分明确,即使进行改造和升级也很方便。
  • 依赖
    • CSS transition:无需额外依赖,只要浏览器支持 CSS3,就可以使用,就像一个不依赖任何道具就能表演的街头艺人,随时可以开始表演。
    • Framer - motion:需要安装 framer - motion 库,增加了项目的依赖项,但换来的是强大的动画和交互能力,就像一个需要借助专业舞台和道具才能展现出最佳表演效果的艺术家,虽然有一定的依赖,但能带来更精彩的演出。

综上所述,CSS transition 和 framer - motion 各有优劣。如果你的项目中只是需要一些简单的动画效果,如元素的淡入淡出、简单的缩放等,那么 CSS transition 是一个不错的选择,它简单高效,无需引入额外的库;但如果你的项目对动画效果和交互性有较高的要求,比如需要实现复杂的动画序列、物理效果、手势交互等,那么 framer - motion 绝对能满足你的需求,帮助你打造出更加炫酷和富有交互性的用户界面。在实际开发中,我们可以根据具体的项目需求和场景,灵活选择使用这两种动画方式,让我们的网页应用更加生动有趣,吸引用户的目光😎。

八、总结与展望

image.png

在探索 React 动画的奇妙旅程中,我们深入了解了 framer - motion 这个强大的动画库,它就像是一把神奇的钥匙,为我们打开了通往无限动画创意的大门。

从最初的快速上手,到深入探究核心属性,再到挖掘各种进阶特性,我们一步步领略了 framer - motion 的魅力。它不仅提供了简单直观的方式来实现基本动画,如淡入淡出、平移、旋转等,还具备强大的功能来处理复杂的动画场景,如管理多个动画状态、实现动画与交互的完美结合、制作创意十足的复杂动画以及创建适配不同屏幕的响应式动画。与传统的 CSS transition 相比,framer - motion 在动画能力、交互性和维护性等方面都展现出了明显的优势,为我们打造高质量的用户界面提供了有力的支持。

亲爱的读者们,现在就行动起来吧!在你的下一个 React 项目中尝试使用 framer - motion ,发挥你的想象力和创造力,将那些平淡无奇的页面转变为充满活力和魅力的交互世界。相信你一定会被它的强大功能所折服,开启一段充满惊喜的动画开发之旅!