新闻详情

新闻详情

首页 / 资讯中心 / 详情

rsuite Animation.Transition 自定义动画完全指南:从状态机原理到 Zoom / Flip / Rotate / Bounce 实战

发布时间:2026/9/25 3:37:09来源:尧图网络
rsuite Animation.Transition 自定义动画完全指南:从状态机原理到 Zoom / Flip / Rotate / Bounce 实战
前端UI组件【免费下载链接】rsuite A suite of React components .项目地址https://gitcode.com/gh_mirrors/rs/rsuite点击查看免费下载rsuite内置了Animation组件族其中Animation.Transition是自由度最高的底层组件它不绑定任何预设动画而是通过四个阶段 className 与 CSSanimation的配合让你完全掌控进入/退出动画的每个细节。本篇以 transition.md 中的官方示例为主体深入剖析Transition的状态机实现、四个阶段 className 的切换机制并完整复现 Zoom、Flip、Rotate、Bounce 四种自定义动画的完整可运行代码。Transition 在 Animation 组件族中的定位Animation组件族由 src/Animation/index.tsx 统一导出包含 5 个成员组件类型说明Animation.FadeFunctionComponent淡入淡出动画Animation.CollapseComponentType折叠高度/宽度动画Animation.BounceFunctionComponent弹跳动画Animation.SlideFunctionComponent滑入滑出动画Animation.TransitionComponentType自定义动画本文主角其中Fade、Bounce、Slide、Collapse都是基于Transition封装的上层组件——例如 Bounce.tsx 内部就是给Transition传入animation、timeout{300}以及预设的bounce-in/bounce-outclassNameSlide.tsx 则是根据placement拼接出slide-in-right之类的 className。因此理解了Transition就等于理解了整个动画体系的底层原理。四个阶段 className自定义动画的唯一入口Transition的核心设计是动画本身完全交给 CSS组件只负责按状态切换 className。文档明确给出了四个阶段 className 的配置方式exitedClassNamecustom-exited exitingClassNamecustom-exiting enteredClassNamecustom-entered enteringClassNamecustom-entering对应四种状态见 src/Animation/Transition.tsx 的STATUS枚举className触发时机语义exitedClassName退出完成后STATUS.EXITED元素保持隐藏最终态exitingClassName退出动画进行中STATUS.EXITING播放退出动画enteringClassName进入动画进行中STATUS.ENTERING播放进入动画enteredClassName进入完成后STATUS.ENTERED元素保持显示最终态在render()方法中Transition.tsx组件根据当前状态只挂载对应阶段的 className其他 className 会被移除。这意味着你可以在四个类上分别定义不同的animation-name实现进入用一套动画、退出用另一套动画的效果。内置的四个生命周期回调除了 classNameTransition还暴露了 6 个生命周期回调供你在动画关键节点挂接业务逻辑onEnter进入动画开始前触发onEntering进入动画开始后触发onEntered进入动画结束后触发onExit退出动画开始前触发onExiting退出动画开始后触发onExited退出动画结束后触发从源码看Transition.tsxperformEnter/performExit会依次调用这三个回调并通过onTransitionEnd监听animationend或transitionend事件事件完成后才推进到下一状态。值得注意的是Transition.spec.tsx 的测试用例明确验证了依次调用 onEnter/onEntering/onEntered以及依次调用 onExit/onExiting/onExited的行为这套回调顺序是有测试保障的。完整实战一个面板切换四种动画下面复现官方示例完整代码见 transition.md用一个 240×120 的渐变卡片做面板通过四个按钮切换 Zoom / Flip / Rotate / Bounce 四种动画每次点击同时切换show状态让面板在进入和退出时各播放一次动画。组件骨架函数式 children ref 转发import { Animation, Button, ButtonToolbar, Card } from rsuite; const AnimatedPanel React.forwardRef(({ ...props }, ref) ( Card {...props} ref{ref} shaded bordered{false} w{240} h{120} cwhite bglinear-gradient(45deg, #4CAF50, #2196F3) div Card.HeaderCustom Transition/Card.Header Card.BodyClick different buttons to see various animation effects!/Card.Body /div /Card ));注意这里的关键点Animation.Transition的 children 是函数形式(props, ref) ReactNode。组件内部会把当前阶段的 className 合并进props.className并把ref传给你见 Transition.tsx。因此业务组件必须通过React.forwardRef接收并透传refTransition 才能拿到真实 DOM 节点来监听animationend事件。若直接传 React 元素Transition 也会用React.cloneElement自动注入ref和 classNameTransition.tsx两种写法都受测试覆盖。状态与事件处理const App () { const [show, setShow] React.useState(true); const [effect, setEffect] React.useState(zoom); const onChange newEffect { setShow(!show); setEffect(newEffect); }; return ( div Styles / ButtonToolbar Button appearanceprimary onClick{() onChange(zoom)}Zoom/Button Button appearanceprimary onClick{() onChange(flip)}Flip/Button Button appearanceprimary onClick{() onChange(rotate)}Rotate/Button Button appearanceprimary onClick{() onChange(bounce)}Bounce/Button /ButtonToolbar hr / div Animation.Transition exitedClassName{custom-exited custom-${effect}-exited} exitingClassName{custom-exiting custom-${effect}-exiting} enteredClassName{custom-entered custom-${effect}-entered} enteringClassName{custom-entering custom-${effect}-entering} in{show} {(props, ref) AnimatedPanel {...props} ref{ref} /} /Animation.Transition /div /div ); };in属性是动画的开关in{true}触发进入动画in{false}触发退出动画默认值及初始状态逻辑见 Transition.tsx。这里把effect拼进 className实现了同一组件动态切换动画效果的效果。配合unmountOnExit属性退出动画结束后组件会被从 DOM 中卸载Transition.tsx适合弹层、抽屉这类需要彻底移除的场景。CSS 动画定义进入与退出各一套 keyframes官方示例的核心 CSS 如下。通用规则先保证动画时长与缓动一致.custom-exiting, .custom-entering { animation: 0.5s cubic-bezier(0.4, 0, 0.2, 1); animation-fill-mode: forwards; }接着为每个效果分别定义*-entering/*-exiting类指向对应的keyframes下面按效果逐一给出完整代码。Zoom缩放进入从 0.3 倍放大并淡入退出反向收缩淡出。.custom-zoom-exiting { animation-name: zoomOut; } .custom-zoom-entering { animation-name: zoomIn; } keyframes zoomIn { from { opacity: 0; transform: scale3d(0.3, 0.3, 0.3); } 50% { opacity: 1; } } keyframes zoomOut { from { opacity: 1; } 50% { opacity: 0; transform: scale3d(0.3, 0.3, 0.3); } to { opacity: 0; } }Flip翻转使用perspective(400px)配合rotate3d沿 X 轴翻转中途有回弹-20deg → 10deg → -5deg模拟 3D 翻牌效果。.custom-flip-exiting { animation-name: flipOut; } .custom-flip-entering { animation-name: flipIn; } keyframes flipIn { from { opacity: 0; transform: perspective(400px) rotate3d(1, 0, 0, 90deg); } 40% { transform: perspective(400px) rotate3d(1, 0, 0, -20deg); } 60% { opacity: 1; transform: perspective(400px) rotate3d(1, 0, 0, 10deg); } 80% { transform: perspective(400px) rotate3d(1, 0, 0, -5deg); } to { transform: perspective(400px); } } keyframes flipOut { from { transform: perspective(400px); } 30% { opacity: 1; transform: perspective(400px) rotate3d(1, 0, 0, -20deg); } to { opacity: 0; transform: perspective(400px) rotate3d(1, 0, 0, 90deg); } }Rotate旋转围绕 Z 轴旋转 180° 并缩放。.custom-rotate-exiting { animation-name: rotateOut; } .custom-rotate-entering { animation-name: rotateIn; } keyframes rotateIn { from { opacity: 0; transform: rotate3d(0, 0, 1, -180deg) scale(0.3); } 50% { opacity: 1; } } keyframes rotateOut { from { opacity: 1; } to { opacity: 0; transform: rotate3d(0, 0, 1, 180deg) scale(0.3); } }Bounce弹跳进入时先放大再回弹1.1 → 0.9 → 1.03 → 0.97退出时反向弹动后消失。.custom-bounce-exiting { animation-name: bounceOut; } .custom-bounce-entering { animation-name: bounceIn; } keyframes bounceIn { from { opacity: 0; transform: scale3d(0.3, 0.3, 0.3); } 20% { transform: scale3d(1.1, 1.1, 1.1); } 40% { transform: scale3d(0.9, 0.9, 0.9); } 60% { opacity: 1; transform: scale3d(1.03, 1.03, 1.03); } 80% { transform: scale3d(0.97, 0.97, 0.97); } to { opacity: 1; transform: scale3d(1, 1, 1); } } keyframes bounceOut { 20% { transform: scale3d(0.9, 0.9, 0.9); } 50%, 55% { opacity: 1; transform: scale3d(1.1, 1.1, 1.1); } to { opacity: 0; transform: scale3d(0.3, 0.3, 0.3); } }进入/退出的最终落点动画结束后类名切换到enteredClassName/exitedClassName因此还要定义这两个类的静态样式否则元素可能停留在动画中间帧.custom-entered { opacity: 1; } .custom-exited { opacity: 0; }原理Transition 内部的状态机与事件监听从源码结构看Transition是一个基于 5 个状态UNMOUNTED、EXITED、ENTERING、ENTERED、EXITING的状态机组件初始状态in{true}且未开启transitionAppear时直接进入ENTERED不播放动画in{false}且开启unmountOnExit时初始为UNMOUNTEDTransition.tsx。状态推进in变化时在componentDidUpdate中调用performEnter/performExit先把状态切到ENTERING/EXITING挂载对应的 entering/exiting className。动画结束判定onTransitionEnd同时监听animationendanimation为 true 时事件名由 utils.ts 中的getAnimationEnd()根据浏览器嗅探返回webkitAnimationEnd或animationend与一个基于timeout的兜底setTimeoutTransition.tsx两者任一先到都会把状态推进到ENTERED/EXITED并切换 className。卸载与安全回调unmountOnExit开启时退出动画完成后组件返回null从 DOM 卸载setNextCallback与safeSetState机制保证了组件卸载后不再触发回调Transition.tsx。其中timeout的默认值是 1000msTransition.tsx它既是事件监听失败时的兜底也决定了动画最长等待时间而Fade、Bounce、Slide等上层组件的默认timeout为 300ms见 Fade.tsx、Bounce.tsx、Slide.tsx使用时建议让timeout与 CSSanimation-duration保持一致或略大避免动画被提前截断。完整 props 参考Animation.Transition的完整 props 定义见 src/Animation/Transition.tsx官方文档 Animation 总览页 也给出了同名参数表属性类型默认值说明enteredClassNamestring进入动画完成后的 classNameenteringClassNamestring进入动画进行中的 classNameexitedClassNamestring退出动画完成后的 classNameexitingClassNamestring退出动画进行中的 classNameinboolean为 true 时显示并播放进入动画onEnter(node?) void进入动画开始前触发onEntering(node?) void进入动画开始时触发onEntered(node?) void进入动画结束后触发onExit(node?) void退出动画开始前触发onExiting(node?) void退出动画开始时触发onExited(node?) void退出动画结束后触发timeoutnumber(1000)动画等待/兜底时长mstransitionAppearboolean首次挂载且in为 true 时也播放进入动画unmountOnExitboolean退出动画结束后从 DOM 卸载组件animationboolean监听animationendtrue还是transitionendfalse扩展思路基于 Transition 的组合用法封装自己的动画组件仿照 Fade.tsx 与 Bounce.tsx 的模式用useStyles(anim)生成带命名空间前缀的 className再包一层Transition即可沉淀出团队可复用的动画组件。与 rsuite 内置动画对比Animation.Fade/Slide/Bounce/Collapse适用于常见交互当需要 3D 翻转、弹性回弹等定制效果时Transition是唯一能完全自定义动画路径的入口。配合弹层组件unmountOnExittransitionAppear组合常用于Modal、Drawer、Tooltip等需要首屏显示 关闭后彻底卸载的组件确保动画期间事件不会泄漏。本篇以官方 transition.md 示例为主线完整给出了 Zoom / Flip / Rotate / Bounce 四套可复制的动画代码并基于 Transition.tsx 源码解释了状态机与事件监听原理。按照文中代码即可在任意 rsuite 项目中落地一套完全自定义的动画方案。赞分享前端UI组件【免费下载链接】rsuite A suite of React components .项目地址https://gitcode.com/gh_mirrors/rs/rsuite点击查看免费下载相关推荐rsuite Animation 组件实战指南Fade、Collapse、Bounce、Slide 与自定义 Transition 动画rsuite Animation 组件实战指南Fade、Collapse、Bounce、Slide 与自定义 Transition 动画 rsuite 的 A前端UI组件SmartRefreshLayout自定义刷新状态管理从原理到实战SmartRefreshLayout自定义刷新状态管理从原理到实战 一、刷新状态管理痛点与解决方案 你是否还在为下拉刷新状态混乱而困扰SmartRefresUI组件移动开发Rsuite Button 加载状态loading实战指南从属性用法到源码实现原理Rsuite Button 加载状态loading实战指南从属性用法到源码实现原理 本文围绕 Rsuite 组件库中 Button 的 loading 状前端UI组件上一篇hekate压缩包解压工具在Switch上处理ZIP/RAR文件下一篇玩转GPT-SoVITS情感合成三步情感控制完整攻略创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

节后康复学习日志:肩关节复合体与SOAP记录的7小时高效实践 2026/9/25 4:56:50

节后康复学习日志:肩关节复合体与SOAP记录的7小时高效实践

春节回来第一周,我最怕的不是肠胃,是书桌。Day1坐在桌前两个小时,光是翻目录就翻了四十分钟,脑子里全是年夜饭的油香和亲戚家小孩的哭声。到了Day2,我干脆不跟生物钟较劲了,把这一天的康复学习定在12:30到2…

阅读更多 →
Python+微信测试号实现每日天气自动推送:从API调用到定时任务 2026/9/25 4:56:44

Python+微信测试号实现每日天气自动推送:从API调用到定时任务

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
Navicat免安装版深度解析:依赖库、配置与MySQL连接排查指南 2026/9/25 4:56:44

Navicat免安装版深度解析:依赖库、配置与MySQL连接排查指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
从能跑到敢上线:Agent Skill 质量三道门槛与测试上线全流程 2026/9/25 4:56:44

从能跑到敢上线:Agent Skill 质量三道门槛与测试上线全流程

1. 从"能跑"到"敢上线":Skill 质量的三道门槛写 Skill 这件事,门槛其实比大多数人想象的要低。一个SKILL.md加几个脚本,跑通一次 Demo,看起来就"成了"。但我自己踩过的坑告诉我:能跑通的…

阅读更多 →
HDFS基本操作本质:理解NameNode与DataNode协同机制 2026/9/25 4:56:43

HDFS基本操作本质:理解NameNode与DataNode协同机制

1. 为什么“HDFS基本操作”不是命令背诵,而是理解分布式文件系统的第一道门槛刚接触Hadoop生态时,我带过一批实习生,他们花两小时把hdfs dfs -ls /、-mkdir、-put这些命令抄在小本子上,信心满满地去跑第一个任务——结果卡在-put上…

阅读更多 →
中国移动H10G-13融合网关刷机攻略:晶晨S905L3芯片刷安卓9完整教程 2026/9/25 4:56:43

中国移动H10G-13融合网关刷机攻略:晶晨S905L3芯片刷安卓9完整教程

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉