恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
使用 Framer Motion 为 React 应用打造文本与图片动画:Refine 项目实战指南
首页
资讯中心
/
使用 Framer Motion 为 React 应用打造文本与图片动画:Refine 项目实战指南
使用 Framer Motion 为 React 应用打造文本与图片动画:Refine 项目实战指南
发布时间:2026/9/10 20:01:27
使用 Framer Motion 为 React 应用打造文本与图片动画Refine 项目实战指南【免费下载链接】refineA React Framework for building internal tools, admin panels, dashboards B2B apps with unmatched flexibility.项目地址: https://gitcode.com/GitHub_Trending/re/refine本文以 Refine 仓库官方博客中的 Framer Motion 教程为主体系统讲解如何在 React 应用中用极少量代码实现文本入场动画、悬停反馈以及图片旋转轮播、拖拽与点按缩放等交互动画并对照 Refine 文档站源码documentation/package.json 与 documentation/src/refine-theme 等展示该库在真实项目中的落地方式。读完本文你将掌握motion组件、animate/initial/transition/whileHover/whileTap/drag等核心 props 的用法并能直接复制代码到自己的 React 项目中运行。Framer Motion 是什么Framer Motion 是 Framer 团队推出的、可投入生产环境的 React 动画库它能够直接在 DOM 元素上创建多种动画效果是编写复杂 CSS 动画的优秀替代方案。相比手写大量 CSS keyframesFramer Motion 把动画声明收敛为组件上的 props让开发者把精力集中在业务本身。在使用它之前需要在 React 项目中安装依赖并导入所需组件。环境准备跟随本文动手实践前需要具备对 HTML、CSS、JavaScript 基础前端技术有清晰理解了解 React.js 基础知识本机已安装 Node.js。React 项目中的外部库统一通过包管理器安装执行npm install framer-motion安装完成后在需要使用动画的组件中导入 Framer Motion 的组件即可开始编码。本文内容分为两部分先完成文本动画再完成图片动画最后两者共同组成一个完整的 React 应用。文本动画用 motion 组件让标题动起来认识 motion 组件在App.js中加入如下代码import { motion } from framer-motion; function App() { return ( div classNameApp motion.h1 animate{{ x: [50, 150, 50], opacity: 1, scale: 1 }} transition{{ duration: 5, delay: 0.3, ease: [0.5, 0.71, 1, 1.5], }} initial{{ opacity: 0, scale: 0.5 }} whileHover{{ scale: 1.2 }} Animation made easy with Framer Motion /motion.h1 /div ); } export default App;注意这里的h1与标准h1元素的差别它使用了motion前缀。motion组件是使用 Framer Motion 制作动画的第一步它可以配合任意标准 HTML 元素使用motion.div、motion.h1、motion.button等其本质是把 HTML 元素封装成 React 组件再通过 props 驱动动画。initial 与 animate声明动画的起点与终点为了让文本在页面加载时拥有一个渐显的入场动画我们同时使用了initial和animate两个 propsinitial定义元素的初始状态这里设置为{ opacity: 0, scale: 0.5 }即一开始文字透明且缩小到一半animate定义元素的动画目标状态这里设置为{ opacity: 1, scale: 1 }即最终完全显示并恢复原始大小。Framer Motion 会自动计算并补间这两个状态之间的过渡。此外animate还支持传入关键帧数组让元素按顺序经过多个值。代码中的x: [50, 150, 50]表示文本沿 x 轴从 50 移动到 150再回到 50原文中给出的写法为x: [0, 150, 50]效果等价均表示一个往返移动。opacity取 1、scale取 1当缩放达到 1 时文本停止增大尺寸避免“狂野”的视觉效果。transition控制动画节奏每一个有效的动画都离不开过渡过程。transitionprop 用来描述动画如何播放包括三个关键参数duration动画持续时长秒示例中为 5delay动画开始前的延迟时长秒示例代码中为 0.3原文叙述中写作 3以代码 0.3 为准可让入场衔接更自然ease缓动函数。示例使用贝塞尔曲线数组[0.5, 0.71, 1, 1.5]原文叙述中写作[0.5, 0.71, 1, 1.01]它描述了文本动画在进入原始缩放值之前以怎样的速率进行改变数组即可获得不同的“弹入”节奏。参数一致性提示原文档正文对delay与ease数值的描述和代码示例略有出入实际运行时以组件代码中的取值为准。这也提醒我们动画参数往往需要肉眼微调建议以transition中的代码为准进行调试。whileHover悬停放大效果光有入场动画还不够我们再为文本加上悬停反馈当鼠标悬停在文字上时文字像被“弹起”一样略微变大。function App() { return ( div classNameApp motion.h1 ... // highlight-next-line whileHover{{ scale: 1.2 }} Animation made easy with Framer Motion /motion.h1 /div ); }whileHover是 Framer Motion 的手势gestureprops之一它声明元素在悬停状态下应呈现的目标样式。这里scale: 1.2表示悬停时放大到原始尺寸的 1.2 倍松开鼠标后自动回到原状无需手动编写任何事件监听或 CSS 类切换。图片动画构建带旋转、拖拽与点按反馈的轮播组织图片资源首先在src目录下创建images文件夹存放图片然后在src下新建image.js集中导入所有图片import fox from ./images/pexels-fox-1071249.jpg; import jill from ./images/jill.jpg; import cha1 from ./images/cha1.jpg; import cha2 from ./images/cha2.jpg; export default [fox, jill, cha1, cha2];把所有图片统一收拢到image.js再导出数组可以避免在App.js中反复 import 同一批图片减少冗余代码。编写样式在App.css中加入轮播所需的基础样式.item { min-height: 10rem; min-width: 30rem; padding: 5px; } .item img { width: 60%; height: 50%; border-radius: 1rem; pointer-events: none; padding: 15%; } .inner-carousel { display: flex; background: rgb(76, 76, 76); height: 23rem; } .carousel { cursor: grab; overflow: hidden; background: rgb(215, 216, 215); height: 23rem; }其中.carousel负责裁剪溢出内容并呈现“手抓”光标.inner-carousel使用 flex 排列图片.item img中的pointer-events: none避免图片自身拦截拖拽事件。三层容器结构与旋转动画修改App.js为如下代码实现一个带旋转效果的轮播import { motion } from framer-motion; import ./App.css; import images from ./image; function App() { return ( div classNameApp motion.div classNamecarousel motion.div animate{{ scale: [1, 1, 1, 1, 1], rotate: [0, 30, 60, 240, 360], }} {images.map((image) { return ( motion.div whileHover{{ scale: 1.2 }} whileTap{{ scale: 2 }} classNameitem transition{{ duration: 3 }} key{image} img srchttps://refine.ams3.cdn.digitaloceanspaces.comundefined altCarousel image placeholder / /motion.div ); })} /motion.div /motion.div /div ); } export default App;整个动画的形态是页面每次刷新时轮播执行一次旋转鼠标靠近图片时触发悬停效果触摸图片时触发点按效果。实现上需要三个容器从外到内依次是外层轮播容器、内层旋转容器、图片容器三者全部使用 Framer Motion 的motion组件层层嵌套内层容器承担旋转与滑动效果通过animateprop 将scale设为[1, 1, 1, 1, 1]、rotate设为[0, 30, 60, 240, 360]让图片组完成一整圈 360° 的独特旋转最内层图片容器负责逐张渲染从image.js导入的图片。占位说明原文示例中img src使用了占位 URL实际接入时请改为src{image}引用images数组中映射出的真实图片地址即可正确显示轮播内容。拖拽与回弹drag 系列 props为了让轮播具备“可拖拽”的类轮播手感给内层旋转容器加上drag与dragConstraintsfunction App() { return ( div classNameApp motion.div classNamecarousel motion.div ... // highlight-start dragx dragConstraints{{right: 0, left:-1100}} dragTransition{{ bounceStiffness: 600, bounceDamping: 8 }} // highlight-end ... /motion.div /motion.div /div ); }dragx只允许沿 x 轴水平方向拖拽因为轮播需要左右滑动dragConstraints{{ right: 0, left: -1100 }}设置拖拽边界让轮播向左最多移动 1100px随后返回到原位相当于一个行程挡板dragTransition{{ bounceStiffness: 600, bounceDamping: 8 }}为拖拽末端增加弹跳感。bounceStiffness控制回弹的“刚性”600 表示回弹较有力度bounceDamping控制回弹阻尼8 表示衰减较快、摆动几次即稳定两者配合即可在每次拖到尽头时呈现自然的橡皮筋回弹效果。悬停与点按whileHover 与 whileTap轮播中最内层的图片容器用于承载图片并定义交互动画function App() { return ( div classNameApp motion.div classNamecarousel motion.div {images.map((image) { return ( motion.div ... //highlight-start whileHover{{ scale: 1.2 }} whileTap{{ scale: 2 }} //highlight-end img srchttps://refine.ams3.cdn.digitaloceanspaces.comundefined altCarousel image placeholder / /motion.div ); })} /motion.div /motion.div /div ); }whileHover{{ scale: 1.2 }}鼠标悬停时图片最多放大到 1.2 倍whileTap{{ scale: 2 }}按下/触摸时放大到 2 倍释放后回弹形成活泼的“点按弹跳”反馈同时为该容器设置transition{{ duration: 3 }}示例取值可按需缩短至 0.3~0.5 秒获得更跟手的交互让悬停与点按动画更平滑自然。与纯 CSS 相比以上旋转、拖拽、回弹、悬停、点按效果全部由几行 props 声明完成无需维护复杂的keyframes与手势状态机这正是 Framer Motion 的核心价值。仓库实证Refine 文档站中的 Framer Motion 应用Framer Motion 并非只在教程里出现Refine 仓库的文档站点本身就重度使用它。这为理解该库的“真实项目用法”提供了第一手源码证据。依赖版本在 documentation/package.json 中可以看到文档站依赖声明framer-motion: ^6.5.1即当前仓库使用的是 Framer Motion 6.x 版本线。博客阅读进度条useScroll useTransformdocumentation/src/refine-theme/blog-header.tsx 中的BlogHeader组件演示了典型的滚动联动动画import { motion, useScroll, useTransform } from framer-motion; // ... const { scrollYProgress } useScroll(); const progressPercentage useTransform( scrollYProgress, [0.03, 0.95], [0%, 100%], );useScroll()返回页面滚动进度 motion valueuseTransform将其映射为百分比字符串再通过style{{ width: progressPercentage }}绑定到motion.div上形成随滚动推进的顶部进度条。这与教程中“把动画值绑定到元素样式”的思路一脉相承。首页能力轮播useMotionValue useTransform animatedocumentation/src/refine-theme/landing-magic.tsx 中的LandingMagic组件在首页用useMotionValue(0)维护序列值再用useTransform把序列映射为纵向位移百分比[0%, -...%]最后通过命令式animate(sequence, nextValue, { type: spring, bounce: 0.35, stiffness: 50 })驱动一组数据源/UI 库图标循环滚动效果与教程中的旋转轮播异曲同工——都用 motion value 驱动 transform 变换。数字滚动计数器animate onUpdatedocumentation/src/hooks/use-animated-counter.tsx 封装了一个useAnimatedCounterhookconst controls animate(initialValue, maxValue, { duration, ease: easeOut, onUpdate(value) { setCounter(value); }, }); return () controls.stop();它用animate()在指定时长内从初始值插值到目标值每帧通过onUpdate回调刷新 React state并在卸载时调用controls.stop()清理动画。这是 Framer Motion 在非视觉、数值型动画场景下的典型用法。抽屉与滚动偏移useScrolldocumentation/src/refine-theme/common-drawer.tsx 中的抽屉组件通过useScroll()监听scrollY用scrollY.onChange动态计算顶部偏移量保证抽屉在滚动条移动时仍然对齐公告栏——印证了 motion value 的可订阅特性在真实布局逻辑中的作用。此外documentation/src/refine-theme 目录下的doc-survey-widget.tsx、doc-thumbs-up-down-feedback-widget.tsx、landing-sweet-spot.tsx等组件还导入了AnimatePresence、motion、useInView用于反馈小组件的进出场动画与视口检测说明AnimatePresence列表项/条件渲染元素的离场动画和useInView元素进入视口时触发动画同样是日常项目的高频能力。Framer Motion 常用 props 速查结合教程与仓库源码将本文涉及的 props 归纳如下Prop作用本文示例取值motion.*将任意 HTML 元素包装为可动画组件motion.h1、motion.divinitial定义动画的初始状态{ opacity: 0, scale: 0.5 }animate定义动画目标状态或关键帧序列{ x: [50, 150, 50], opacity: 1, scale: 1 }、{ rotate: [0, 30, 60, 240, 360] }transition控制时长、延迟与缓动{ duration: 5, delay: 0.3, ease: [0.5, 0.71, 1, 1.5] }whileHover悬停手势的目标状态{ scale: 1.2 }whileTap点按/触摸手势的目标状态{ scale: 2 }drag启用拖拽并限定轴向xdragConstraints限制拖拽边界{ right: 0, left: -1100 }dragTransition拖拽回弹物理参数{ bounceStiffness: 600, bounceDamping: 8 }useScroll订阅页面/元素滚动进度const { scrollYProgress } useScroll()useTransform将一个 motion value 映射为另一个useTransform(scrollYProgress, [0.03, 0.95], [0%, 100%])useMotionValue创建可订阅的数值源useMotionValue(0)animate命令式地驱动动画animate(0, 100, { duration, onUpdate })总结本文从零开始演示了 Framer Motion 在 React 应用中的两种典型动画用motion组件配合initial/animate/transition/whileHover完成的文本入场与悬停放大以及用嵌套motion容器配合animate旋转关键帧、drag/dragConstraints/dragTransition拖拽回弹、whileHover/whileTap缩放反馈构建的图片轮播。相比手写 CSS 动画这些效果仅需寥寥数行声明式 props 即可完成。同时Refine 文档站源码blog-header.tsx、landing-magic.tsx、use-animated-counter.tsx、common-drawer.tsx证明了这些 API 在生产环境中的真实价值进度条、轮播、计数器、抽屉偏移乃至进离场动画都可借助 Framer Motion 以声明式、低样板的方式落地。Framer Motion 还提供 Variants、AnimatePresence、useInView、useSpring、useVelocity等更强大的能力值得在此基础上继续探索。【免费下载链接】refineA React Framework for building internal tools, admin panels, dashboards B2B apps with unmatched flexibility.项目地址: https://gitcode.com/GitHub_Trending/re/refine创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考