Framer Motion 一个生产级 React 动画库

1,055 阅读4分钟

一、Framer Motion 简介

Framer Motion 是一个面向创意专业人士的 Web 构建器、简单但功能强大的 React 运动库。

1.1) 特点

  • 🌻 Framer Motion 是 React 生产级的动画库。
  • 🌻 Framer Motion 目前支持 React18、React 组件和 React Hooks。
  • 🌻 Framer Motion 支持过渡动画、布局动画、关键帧动画、进入-退出动画、动画变种、手势动画、滚动动画、3D动画和无障碍等。
  • ...

二、安装

<npm_manager> add framer-motion

三、Api 一览

了解 api 知道 frame motion 大概干了哪些事情,对我们全面了解 frame motion 更有帮助

3.1)组件

Framer Motion 可以基于 React 组件完成动画编码工作:

function Component() {
    return <div>
        <motion.div /> // 🍀运动组件是针对 60fps 动画和手势优化的 DOM 基元。
        <AnimatePresence /> // 🍀当组件从 React 树中删除时,对其进行动画处理。
        <LayoutGroup /> // 🍀将应一起执行布局动画的运动组件分组。
        <LazyMotion /> // 🍀过延迟加载 Motion 功能的子集来减小包大小。
        <MotionConfig /> // 🍀设置 Framer Motion 的配置选项。
        <Reorder /> // 🍀使用一组简单的组件创建拖动重新排序效果。
    </div>
}

3.2)motion 值

使用钩子函数创建 motion value:

动画或视频制作过程中,每一帧的运动值。这可以理解为每一帧中对象的位置、旋转、缩放等属性的变化。这些变化值描述了动画的运动轨迹和动态效果。

function Ho() {
    const e = useMotionValueEvent(); // 🌹订阅来自 React 组件的运动值事件。
    const t = useMotionTemplate(); // 🌹通过字符串模板将多个运动值合并为一个新值。
    const s = useScroll(); // 🌹使用 useScroll 挂钩创建滚动链接动画。
    const sp = useSpring(); // 🌹通过弹簧使其目标产生动画的运动值。
    const ti = useTime(); // 🌹一个运动值,用于更新每个动画帧自创建以来的持续时间(以毫秒为单位)。
    const tr = useTransform(); // 🌹创建一个新的运动值来转换一个或多个其他运动值的输出。
    const v = useVelocity(); // 🌹创建一个跟踪另一个速度的运动值。
    const wc = useWillChange(); // 🌹自动管理将更改的 CSS 属性以优化性能。
}

3.3)通用函数

api简介
animate手动管理和控制动画
scroll基于 ScrollTimeline创建滚动链接动画
inView当元素进入和离开视口时触发回调
transform创建一个函数,将值从一个范围映射到另一个范围。
stagger跨元素交错动画的函数。
frame安排一个函数在 Motion 的动画循环上运行。
easing function一组强大的缓动函数,可与任何动画库一起使用

3.4)hooks

钩子简介
useAnimate使用范围选择器和自动清理创建动画函数。
useAnimationFrame将最新帧时间输出到所提供的回调的动画循环。
useDragControls手动开始/停止拖动运动组件。
useInView当元素位于视口内时的简单状态挂钩。
useReducedMotion确定用户是否喜欢减少动作的钩子。

3.5)3d

Framer Motion 3D 是一个简单但功能强大的 React Three Fiber 动画库。

  • 🏄‍♂️安装:npm install three @react-three/fiber framer-motion-3d
  • 🏄‍♂️基本用法:
import { motion } from "framer-motion-3d"

function App() {
    return <motion.pointLight animate={{ x: 2 }} />
}

-🏄‍♂️相机和canvas 画布

import { MotionCanvas, LayoutCamera } from "framer-motion-3d"

export function Scene() {
  <MotionCanvas>
    <LayoutCamera position={[0, 0, 5]} />
    <Box />
  </MotionCanvas>
}

3.6)无障碍

  • 🉑"Reduced Motion" 概念,动画可能会造成人的不适。

Framer Motion 中使用:

  • 👋reducedMotion
  • 👋useReducedMotion

实现无障碍动画,减少和控制动画行为。

四、过渡动画

import { motion } from "framer-motion";

const AnimatedDiv = () => {
  return (
    <motion.div
      animate={{ x: 100, opacity: 0.5 }}
      transition={{ duration: 1 }}
    >
      Hello, Framer Motion!
    </motion.div>
  );
};

过渡动画的其他类型:

  • 🌴tween
  • 🌴spring
  • 🌴inertia

五、变体动画

const variants = {
  hidden: { opacity: 0 },
  visible: { opacity: 1 }
};

<motion.div
  initial="hidden"
  animate="visible"
  variants={variants}
>
  Hello, Framer Motion!
</motion.div>

使用 initial 和 animate 指定变体类型,variants 指定变体样式。

六、手势动画

  • 👅hover
  • 👇tap
  • 🤳拖拽
<motion.div
  whileHover={{ scale: 1.1 }}
  whileTap={{ scale: 0.9 }}
>
  Hover me!
</motion.div>

使用 whileHover 指定 hover 动画,使用 whileTap 指定 tap 动画。

使用拖拽添加拖拽即可:

import { motion } from "framer-motion"

export const MyComponent = () => (
  <motion.div
    drag
    dragConstraints={{
      top: -50,
      left: -50,
      right: 50,
      bottom: 50,
    }}
  />
)

七、布局动画

  • 🍃属性:layout(layoutId)
  • 🍃属性:layoutRoot (存在父子关系时)
  • 🍃组件:LayoutGroup 组件
function Accordion() {
  const [isOpen, setOpen] = useState(false)
  
  return (
    <motion.div
      layout
      style={{ height: isOpen ? "100px" : "500px" }}
      onClick={() => setOpen(!isOpen)}
    />
  )
}

当我们的元素布局发生了变化的时候,我们就可以使用 layout 属性。

八、SVG 动画

  • 🌵线条
<motion.circle />
<motion.line />
  • 🌵路径
function DSvg() {
    return <svg width="400" height="400">
      <g transform="translate(10 10) scale(17 17)">
        <motion.path fill={fill} d={path} />
      </g>
    </svg>
}

九、路由动画

路由之间切换的有时候也非常重要 motion 可以使用 AnimatePresence 实现淡入淡出效果。

function App() {
    return <AnimatePresence mode="wait">
      {your_component}
    </AnimatePresence>
}

十、官方示例

Remix Motion Learn 复刻一个官方的示例。需要学习的小伙伴可以学习一下。

十一、小结

本文主要试图全面了解 frame-motion 的功能,frame-motion 简单易用,能简化动画的开发,同时也提供了 Reduced Motion 减少动画无障碍方案。开源免费值得学习。希望能够帮助到大家。