FramerMotion动画库Skill framer-motion

Framer Motion 是一个用于 React 和 Next.js 应用程序的强大动画库。它提供声明式的动画组件、手势支持、页面过渡、滚动动画等功能,帮助开发者轻松创建流畅、高性能的用户界面动画。关键词:React动画库,Framer Motion教程,页面过渡动画,手势交互,滚动触发动画,UI动画,前端开发,Next.js动画。

前端开发 0 次安装 0 次浏览 更新于 3/2/2026

name: framer-motion description: 用于React的综合性Framer Motion动画库。涵盖运动组件、变体、手势、页面过渡和滚动动画。适用于为React/Next.js应用程序添加动画效果。

Framer Motion 技能

用于React应用程序的生产就绪动画。

快速开始

安装

npm install framer-motion
# 或
pnpm add framer-motion

基本用法

import { motion } from "framer-motion";

// 简单动画
<motion.div
  initial={{ opacity: 0 }}
  animate={{ opacity: 1 }}
  transition={{ duration: 0.5 }}
>
  内容
</motion.div>

核心概念

概念 指南
运动组件 reference/motion-component.md
变体 reference/variants.md
手势 reference/gestures.md
钩子 reference/hooks.md

示例

模式 指南
页面过渡 examples/page-transitions.md
列表动画 examples/list-animations.md
滚动动画 examples/scroll-animations.md
微交互 examples/micro-interactions.md

模板

模板 用途
templates/page-transition.tsx 页面过渡包装器
templates/animated-list.tsx 动画列表组件

快速参考

基本动画

<motion.div
  initial={{ opacity: 0, y: 20 }}
  animate={{ opacity: 1, y: 0 }}
  exit={{ opacity: 0, y: -20 }}
  transition={{ duration: 0.3 }}
>
  内容
</motion.div>

悬停与点击

<motion.button
  whileHover={{ scale: 1.05 }}
  whileTap={{ scale: 0.95 }}
  transition={{ type: "spring", stiffness: 400, damping: 17 }}
>
  点击我
</motion.button>

变体

const container = {
  hidden: { opacity: 0 },
  show: {
    opacity: 1,
    transition: { staggerChildren: 0.1 }
  }
};

const item = {
  hidden: { opacity: 0, y: 20 },
  show: { opacity: 1, y: 0 }
};

<motion.ul variants={container} initial="hidden" animate="show">
  {items.map(i => (
    <motion.li key={i} variants={item}>{i}</motion.li>
  ))}
</motion.ul>

AnimatePresence (退出动画)

import { AnimatePresence, motion } from "framer-motion";

<AnimatePresence mode="wait">
  {isVisible && (
    <motion.div
      key="modal"
      initial={{ opacity: 0 }}
      animate={{ opacity: 1 }}
      exit={{ opacity: 0 }}
    >
      模态框内容
    </motion.div>
  )}
</AnimatePresence>

滚动触发

<motion.div
  initial={{ opacity: 0, y: 50 }}
  whileInView={{ opacity: 1, y: 0 }}
  viewport={{ once: true, margin: "-100px" }}
  transition={{ duration: 0.5 }}
>
  滚动到视图中时触发动画
</motion.div>

拖拽

<motion.div
  drag
  dragConstraints={{ left: -100, right: 100, top: -100, bottom: 100 }}
  dragElastic={0.1}
>
  拖拽我
</motion.div>

布局动画

<motion.div layout layoutId="shared-element">
  布局变化时动画的内容
</motion.div>

过渡类型

// 补间 (默认)
transition={{ duration: 0.3, ease: "easeOut" }}

// 弹簧
transition={{ type: "spring", stiffness: 300, damping: 20 }}

// 弹簧预设
transition={{ type: "spring", bounce: 0.25 }}

// 惯性 (用于拖拽)
transition={{ type: "inertia", velocity: 50 }}

缓动函数

// 内置缓动
ease: "linear"
ease: "easeIn"
ease: "easeOut"
ease: "easeInOut"
ease: "circIn"
ease: "circOut"
ease: "circInOut"
ease: "backIn"
ease: "backOut"
ease: "backInOut"

// 自定义三次贝塞尔曲线
ease: [0.17, 0.67, 0.83, 0.67]

减少动画

始终尊重用户偏好:

import { motion, useReducedMotion } from "framer-motion";

function Component() {
  const prefersReducedMotion = useReducedMotion();

  return (
    <motion.div
      initial={{ opacity: 0, y: prefersReducedMotion ? 0 : 20 }}
      animate={{ opacity: 1, y: 0 }}
      transition={{ duration: prefersReducedMotion ? 0 : 0.3 }}
    >
      尊重动画偏好
    </motion.div>
  );
}

// 或使用媒体查询
const variants = {
  initial: { opacity: 0 },
  animate: { opacity: 1 },
};

<motion.div
  variants={variants}
  initial="initial"
  animate="animate"
  className="motion-reduce:transition-none"
>

常见模式

淡入上移

const fadeInUp = {
  initial: { opacity: 0, y: 20 },
  animate: { opacity: 1, y: 0 },
  transition: { duration: 0.4 }
};

<motion.div {...fadeInUp}>内容</motion.div>

交错列表

const container = {
  hidden: { opacity: 0 },
  show: {
    opacity: 1,
    transition: { staggerChildren: 0.1, delayChildren: 0.2 }
  }
};

const item = {
  hidden: { opacity: 0, x: -20 },
  show: { opacity: 1, x: 0 }
};

模态框

<AnimatePresence>
  {isOpen && (
    <>
      {/* 背景遮罩 */}
      <motion.div
        initial={{ opacity: 0 }}
        animate={{ opacity: 1 }}
        exit={{ opacity: 0 }}
        className="fixed inset-0 bg-black/50"
        onClick={onClose}
      />
      {/* 模态框 */}
      <motion.div
        initial={{ opacity: 0, scale: 0.95 }}
        animate={{ opacity: 1, scale: 1 }}
        exit={{ opacity: 0, scale: 0.95 }}
        className="fixed inset-x-4 top-1/2 -translate-y-1/2 ..."
      >
        模态框内容
      </motion.div>
    </>
  )}
</AnimatePresence>

手风琴

<motion.div
  initial={false}
  animate={{ height: isOpen ? "auto" : 0 }}
  transition={{ duration: 0.3, ease: "easeInOut" }}
  className="overflow-hidden"
>
  <div className="p-4">手风琴内容</div>
</motion.div>

最佳实践

  1. 使用变体:代码更清晰,更容易编排
  2. 尊重减少动画:始终检查 useReducedMotion
  3. 谨慎使用 layout:可能开销较大,仅在需要时使用
  4. 退出动画:用 AnimatePresence 包裹
  5. 交互使用弹簧:悬停/点击感觉更自然
  6. 页面过渡使用补间:时间更可预测
  7. GPU加速属性:优先使用 opacityscalexy 而非 widthheight