mcpField
F
framer-motion

framer-motion

github.com/mindrally设计与 UI2873.0k 次安装3 周前更新
代码仓库

关于 framer-motion

为 React 和 TypeScript 中使用 Motion 动画提供实现指导,涵盖性能、无障碍、滚动联动效果与过渡模式。

主要功能

  1. 01Motion API 使用指导
  2. 02变换与透明度性能建议
  3. 03减少动态效果的无障碍支持
  4. 04滚动联动动画
  5. 05退出与页面过渡

适用场景

  1. 01为 React 界面添加动画
  2. 02构建滚动驱动效果
  3. 03遵循减少动态效果设置
  4. 04实现退出和页面过渡

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/mindrally/skills --skill framer-motion

安装后在 Claude Code 中输入/framer-motion确认已加载。

详细介绍

Framer Motion / Motion 动画指南

你是 Framer Motion(现称 Motion)、React 和 TypeScript 专家。创建动画时请遵循以下指南。

核心原则

从正确的程序包导入
  • React 项目中使用 import { motion } from "motion/react"(不要使用 "framer-motion"——它已过时)
  • 该库已从 Framer Motion 更名为 Motion
  • 始终使用最新的 Motion API
性能优先
  • 为获得最佳性能,请为变换属性(x、y、scale、rotate)和 opacity 添加动画
  • 这些属性可以通过硬件加速,且不会触发布局重新计算
  • 避免为会导致布局偏移的属性添加动画,例如 width、height、top、left、margin、padding

硬件加速

正确使用 will-change
// When animating transforms
<motion.div
  style={{ willChange: "transform" }}
  animate={{ x: 100, y: 50, scale: 1.2 }}
/>

// When animating other GPU-accelerated properties
<motion.div
  style={{ willChange: "opacity, transform" }}
  animate={{ opacity: 0.5, x: 100 }}
/>
添加到 willChange 的属性
  • transform——用于 x、y、scale、rotate、skew
  • opacity——用于 opacity 动画
  • filter——用于模糊、亮度等效果
  • clipPath——用于 clip-path 动画
  • backgroundColor——用于背景颜色过渡

动画最佳实践

复杂动画使用变体
const containerVariants = {
  hidden: { opacity: 0 },
  visible: {
    opacity: 1,
    transition: {
      staggerChildren: 0.1
    }
  }
};

const itemVariants = {
  hidden: { y: 20, opacity: 0 },
  visible: { y: 0, opacity: 1 }
};
共享元素过渡使用 layoutId
<motion.div layoutId="shared-element" />
优先使用 spring 动画
// Springs feel more natural than duration-based animations
<motion.div
  animate={{ x: 100 }}
  transition={{ type: "spring", stiffness: 300, damping: 30 }}
/>

React 集成

通过记忆化提升性能
// Memoize animation variants
const variants = useMemo(() => ({
  hidden: { opacity: 0 },
  visible: { opacity: 1 }
}), []);

// Memoize callbacks
const handleAnimationComplete = useCallback(() => {
  // handler logic
}, []);
避免内联样式对象
// Bad - creates new object on every render
<motion.div style={{ willChange: "transform" }} />

// Good - define outside or memoize
const style = { willChange: "transform" };
<motion.div style={style} />

无障碍

遵循减少动态效果偏好设置
import { useReducedMotion } from "motion/react";

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

  return (
    <motion.div
      animate={{ x: shouldReduceMotion ? 0 : 100 }}
      transition={{ duration: shouldReduceMotion ? 0 : 0.3 }}
    />
  );
}

手势动画

正确使用手势属性
<motion.button
  whileHover={{ scale: 1.05 }}
  whileTap={{ scale: 0.95 }}
  transition={{ type: "spring", stiffness: 400, damping: 17 }}
/>

滚动动画

使用 useScroll 创建滚动关联动画
import { useScroll, useTransform, motion } from "motion/react";

function ParallaxComponent() {
  const { scrollYProgress } = useScroll();
  const y = useTransform(scrollYProgress, [0, 1], [0, -100]);

  return <motion.div style={{ y }} />;
}

退出动画

使用 AnimatePresence 创建退出动画
import { AnimatePresence, motion } from "motion/react";

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

常见模式

错开列表动画
<motion.ul
  initial="hidden"
  animate="visible"
  variants={{
    visible: { transition: { staggerChildren: 0.07 } }
  }}
>
  {items.map((item) => (
    <motion.li
      key={item.id}
      variants={{
        hidden: { opacity: 0, y: 20 },
        visible: { opacity: 1, y: 0 }
      }}
    />
  ))}
</motion.ul>
页面过渡
const pageTransition = {
  initial: { opacity: 0, x: -20 },
  animate: { opacity: 1, x: 0 },
  exit: { opacity: 0, x: 20 },
  transition: { duration: 0.3 }
};

性能调试

  • 使用 React DevTools 检查重新渲染
  • 使用 Chrome DevTools 的 Performance 标签页找出动画卡顿
  • 最低目标为 60fps;在高刷新率显示器上目标为 120fps
  • 在实际设备上测试,尤其是中端 Android 手机

评论

支持 Markdown