
Ant Design Skeleton 组件 active 动画效果全解析从一行代码到 CSS 动画底层实现【免费下载链接】ant-designAn enterprise-class UI design language and React UI library项目地址: https://gitcode.com/gh_mirrors/ant/ant-design导读Skeleton骨架屏是 Ant Design 中最常用的加载占位组件之一而active属性正是让骨架屏从静止的灰色块变成有呼吸感的加载提示的关键开关。本文以components/skeleton/demo/active.md演示为切入点结合仓库源码深入讲解active动画的用法、生效范围、CSS 动画底层实现原理以及它与loading、round等属性的配合技巧帮助你写出既专业又流畅的加载体验。一、active 动画效果两行文档背后的核心能力在仓库的演示文档 components/skeleton/demo/active.md 中对动画效果的描述极为凝练zh-CN显示动画效果。en-USDisplay active animation.与之配套的演示代码位于 components/skeleton/demo/active.tsx完整代码如下import React from react; import { Skeleton } from antd; const App: React.FC () Skeleton active /; export default App;这就是骨架屏动画的一行代码用法在Skeleton /上添加active布尔属性占位图形就会呈现来回扫过的微光效果向用户传达内容正在加载中的信号。虽然演示代码只有一行但其背后涉及active属性的传递链路、CSS Keyframes 动画定义、以及主题 Token 配置等多层实现下面逐一展开。二、active 属性在哪些组件上生效active并非只作用于Skeleton /主组件。从源码结构看Skeleton 是一个复合组件Compound Component通过静态属性挂载了Button、Avatar、Input、Image、Node五个子组件定义于 components/skeleton/Skeleton.tsx#L188-L192Skeleton.Button SkeletonButton; Skeleton.Avatar SkeletonAvatar; Skeleton.Input SkeletonInput; Skeleton.Image SkeletonImage; Skeleton.Node SkeletonNode;因此active动画可以作用于以下全部形态使用方式说明Skeleton active /主骨架屏标题 段落可含头像整体动画Skeleton.Button active /按钮形状骨架屏动画Skeleton.Avatar active /头像骨架屏动画Skeleton.Input active /输入框骨架屏动画Skeleton.Image active /图片骨架屏动画Skeleton.Node active.../Skeleton.Node自定义节点骨架屏动画主组件active 类名的拼接在 components/skeleton/Skeleton.tsx#L163-L176 中active会被拼接到根节点类名上const cls classNames( prefixCls, { [${prefixCls}-with-avatar]: hasAvatar, [${prefixCls}-active]: active, [${prefixCls}-rtl]: direction rtl, [${prefixCls}-round]: round, }, // ... );当active为true时渲染出的 DOM 根节点会带有ant-skeleton-active类默认 prefix 为antCSS 层据此触发动画。子组件active 直接透传以 components/skeleton/Button.tsx#L29-L40 为例子组件同样通过类名拼接响应activeconst cls classNames( prefixCls, ${prefixCls}-element, { [${prefixCls}-active]: active, [${prefixCls}-block]: block, }, className, rootClassName, hashId, cssVarCls, );components/skeleton/Avatar.tsx#L28-L38 中的实现与之对称。这些子组件最终都会把尺寸、形状等参数交给统一的底层元素 components/skeleton/Element.tsx 渲染Element的 props 类型中同样声明了active?: boolean见 components/skeleton/Element.tsx#L4-L12并且支持数字类型的size直接生成像素级宽高。三、动画的底层实现CSS-in-JS 中的 Keyframesactive动画并非由 JavaScript 逐帧驱动而是通过ant-design/cssinjs生成的标准 CSS 动画实现。核心代码位于 components/skeleton/style/index.ts#L44-L51const skeletonClsLoading new Keyframes(ant-skeleton-loading, { 0%: { backgroundPosition: 100% 50%, }, 100%: { backgroundPosition: 0 50%, }, });这个名为ant-skeleton-loading的关键帧动画让背景的backgroundPosition从100% 50%最右侧平移到0 50%最左侧从而产生光带从左向右扫过的视觉效果。动画应用规则动画样式通过genSkeletonColor函数统一生成components/skeleton/style/index.ts#L76-L83const genSkeletonColor (token: SkeletonToken): CSSObject ({ background: token.skeletonLoadingBackground, backgroundSize: 400% 100%, animationName: skeletonClsLoading, animationDuration: token.skeletonLoadingMotionDuration, animationTimingFunction: ease, animationIterationCount: infinite, });关键点说明backgroundSize: 400% 100%背景被放大到容器宽度的 4 倍为渐变光带留出足够的平移空间animationTimingFunction: ease缓动函数让动画在首尾减速观感更自然animationIterationCount: infinite无限循环直到组件卸载或active被关闭。动画的触发范围genBaseStyle中active动画被限定在带-active类名的容器内并一次性作用于所有子占位元素components/skeleton/style/index.ts#L357-L369[${componentCls}${componentCls}-active]: { [ ${skeletonTitleCls}, ${skeletonParagraphCls} li, ${skeletonAvatarCls}, ${skeletonButtonCls}, ${skeletonInputCls}, ${skeletonImageCls} ]: { ...genSkeletonColor(token), }, },也就是说只要在Skeleton active /上开启动画内部的标题-title、段落每一行-paragraph li、头像-avatar、按钮-button、输入框-input、图片-image占位块会同步且统一地播放同一条光带动画整体视觉上非常整齐。光带渐变与动画时长来自 Design Token动画背景的渐变色和时长并不是写死的魔法值而是由主题 Token 提供components/skeleton/style/index.ts#L404-L405skeletonLoadingBackground: linear-gradient(90deg, ${token.gradientFromColor} 25%, ${token.gradientToColor} 37%, ${token.gradientFromColor} 63%), skeletonLoadingMotionDuration: 1.4s,渐变色90 度线性渐变从起点色gradientFromColor默认取colorFillContent过渡到终点色gradientToColor默认取colorFill再回到起点色构成亮-暗-亮的光带动画时长1.4s完成一次完整扫动节奏舒缓不会造成视觉压迫。开发者可以通过主题覆盖gradientFromColor、gradientToColor等 Token 自定义光带配色。需要注意的是旧的color、colorGradientEnd两个 Token 已被标记为废弃源码中通过deprecatedTokens声明了从旧到新的映射关系components/skeleton/style/index.ts#L410-L415。四、与 loading 配合从占位到内容的无缝切换active动画只有在占位状态下才有意义而控制占位状态的是loading属性。在 components/skeleton/Skeleton.tsx#L108 中if (loading || !(loading in props)) { // 渲染骨架屏 } return children ?? null; // 否则渲染真实内容规则解析未传loading属性时始终渲染骨架屏这也是Skeleton active /单独使用即可看到动画的原因loading为true时渲染骨架屏loading为false时直接渲染children传入的真实内容没有子节点则返回null。仓库测试 components/skeleton/tests/index.test.tsx#L45-L58 对该行为有明确覆盖loading{false}且子节点为0时渲染结果文本是0子节点为[1, 2, 3]时渲染出123。因此在实际业务中典型的加载模式是import React, { useEffect, useState } from react; import { Skeleton, Card } from antd; const App: React.FC () { const [loading, setLoading] useState(true); const [data, setData] useStatestring(); useEffect(() { // 模拟异步请求 setTimeout(() { setData(加载完成的内容); setLoading(false); }, 2000); }, []); return ( Card Skeleton active loading{loading} avatar paragraph{{ rows: 4 }} {data} /Skeleton /Card ); }; export default App;数据到达后loading置为false骨架屏连同动画一并消失内容直接呈现全程无需手动控制动画的开关。五、active 动画相关的完整属性速查为了更准确地使用动画效果这里汇总主组件与各子组件中与active相关以及直接影响动画观感的完整属性清单依据 components/skeleton/index.zh-CN.md 的 API 章节整理Skeleton主组件属性说明类型默认值active是否展示动画效果booleanfalseavatar是否显示头像占位图boolean | SkeletonAvatarPropsfalseloading为 true 时显示占位图反之直接展示子组件boolean-paragraph是否显示段落占位图boolean | SkeletonParagraphPropstrueround为 true 时段落和标题显示圆角booleanfalsetitle是否显示标题占位图boolean | SkeletonTitlePropstrueSkeletonAvatarProps属性说明类型默认值active是否展示动画效果仅在单独使用头像骨架时生效booleanfalseshape指定头像的形状circle|square-size设置头像占位图的大小number |large|small|default-SkeletonTitleProps属性说明类型默认值width设置标题占位图的宽度number | string-SkeletonParagraphProps属性说明类型默认值rows设置段落占位图的行数number-width设置段落占位图的宽度若为数组则是对应的每行宽度反之是最后一行的宽度number | string | Arraynumber | string-SkeletonButtonProps属性说明类型默认值版本active是否展示动画效果booleanfalseblock将按钮宽度调整为其父宽度的选项booleanfalse4.17.0shape指定按钮的形状circle|round|square|default-size设置按钮的大小large|small|default-SkeletonInputProps属性说明类型默认值active是否展示动画效果booleanfalsesize设置输入框的大小large|small|default-段落width的逐行宽度逻辑可以在 components/skeleton/Paragraph.tsx#L14-L24 中看到具体实现当width为数组时按索引取对应值为单个值时仅作用于最后一行rows - 1 index。例如paragraph{{ rows: 3, width: [80%, 90%, 60%] }}可构造出前长后短的典型段落效果配合active动画视觉层次更丰富。六、组合形态动画效果在不同骨架元素上的应用active动画与各类骨架元素组合时动画始终生效但占位图形状由各自的shape、size决定。参考 components/skeleton/demo/element.tsx 的交互式演示可以组合出如下形态import React from react; import { Divider, Skeleton, Space, Switch } from antd; import { useState } from react; const App: React.FC () { const [active, setActive] useState(true); return ( Space Skeleton.Button active{active} sizelarge shaperound / Skeleton.Avatar active{active} sizelarge shapecircle / Skeleton.Input active{active} sizelarge / /Space Divider / Skeleton.Button active{active} block / Divider / Skeleton active avatar paragraph{{ rows: 4 }} / Switch checked{active} onChange{setActive} / / ); }; export default App;要点Skeleton.Avatar的shape仅支持circle与squareSkeleton.Button额外支持round胶囊形数字size如Skeleton.Avatar size{40}会被 components/skeleton/Element.tsx#L28-L38 直接转为像素宽高与行高动画开启与否与形状、尺寸完全正交可以自由组合不会互相干扰。七、动画相关的主题定制Design Token如果需要让动画光带更贴合品牌视觉可以通过 ConfigProvider 覆盖 Skeleton 的主题 Token。与动画直接相关的 Token 汇总如下定义于 components/skeleton/style/index.ts#L7-L42Token说明默认推导gradientFromColor渐变色起点颜色colorFillContentgradientToColor渐变色终点颜色colorFilltitleHeight标题骨架屏高度controlHeight / 2blockRadius骨架屏圆角borderRadiusSMparagraphMarginTop段落骨架屏上间距marginLG marginXXSparagraphLiHeight段落骨架屏单行高度controlHeight / 2光带扫描的时长skeletonLoadingMotionDuration默认1.4s属于内部 Token如需调整动画节奏可从全局层面覆盖基础 Token 或直接定制渐变两端的颜色import React from react; import { ConfigProvider, Skeleton } from antd; const App: React.FC () ( ConfigProvider theme{{ components: { Skeleton: { gradientFromColor: #f0f5ff, gradientToColor: #d6e4ff, }, }, }} Skeleton active avatar paragraph{{ rows: 3 }} / /ConfigProvider );结语从 components/skeleton/demo/active.md 中那句显示动画效果到 components/skeleton/demo/active.tsx 的一行Skeleton active /再到 components/skeleton/style/index.ts 中基于 CSS-in-JS 的ant-skeleton-loading关键帧动画Ant Design 把加载中的视觉反馈封装成了一个几乎零成本的属性开关。理解这条从active属性 →-active类名 → Keyframes 动画 → Design Token 的完整链路你就能在列表加载、卡片占位、详情页骨架等场景中用最少的代码交出专业且有质感的加载体验。【免费下载链接】ant-designAn enterprise-class UI design language and React UI library项目地址: https://gitcode.com/gh_mirrors/ant/ant-design创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考