11 KiB
Statistic 统计数值
概述
统计数值(Statistic)是用于展示统计数据的展示类控件。当需要在页面中突出显示某个或某组数字时,如统计数值、倒计时、动画数值等,可以使用 Statistic 组件。
AtomUI 的 Statistic 控件家族完整复刻了 Ant Design 5.0 Statistic 的设计规范,包含三个控件:
| 控件 | 说明 |
|---|---|
Statistic |
基础统计数值,展示格式化的数字或文本 |
TimerStatistic |
计时器/倒计时,基于目标时间自动更新剩余时间 |
StatisticCountUp |
数值递增动画,从 0 动画过渡到目标数值 |
设计原理
Ant Design 的统计数值设计哲学
Ant Design 对 Statistic 的定位是:「当需要突出某个或某组数字时,或展示带描述的统计类数据时使用」。其核心设计理念包括:
- 标题 + 数值的双层结构,标题提供语义上下文,数值是视觉焦点
- 支持前缀/后缀装饰,可放置图标、单位等辅助信息
- 支持数值格式化(千分位分隔符、小数点、精度控制)
- 支持倒计时(Countdown)模式,自动刷新剩余时间
- 支持加载骨架屏(Skeleton),在数据未就绪时显示占位
控件架构设计
AtomUI 的 Statistic 家族采用了基类 + 派生类的设计模式:
HeaderedContentControl (Avalonia)
└── AbstractStatistic (共享基类)
├── Statistic (基础统计数值)
└── TimerStatistic (计时器/倒计时)
TemplatedControl (Avalonia)
└── StatisticCountUp (数值递增动画,作为 Statistic 的 Content 嵌入)
AbstractStatistic 是抽象基类,定义了所有统计数值控件共享的属性和模板结构:
- 标题(
Header,继承自HeaderedContentControl) - 数值格式化参数(
DecimalSeparator、GroupSeparator、Precision) - 前缀/后缀(
ValuePrefixAddOn、ValueSuffixAddOn) - 内容样式(
ContentForeground、ContentFontSize) - 加载状态(
IsLoading)
Statistic 继承 AbstractStatistic,增加了 Value 属性和 Formatter 自定义格式化回调。
TimerStatistic 继承 AbstractStatistic,增加了基于 DispatcherTimer 的自动刷新机制,可用于倒计时和计时。
StatisticCountUp 是独立的控件(继承 TemplatedControl),通过 DoubleTransition 实现从 0 到目标值的动画过渡。它被设计为嵌入 Statistic.Content 中使用。
Avalonia 基础能力
HeaderedContentControl 提供的基础能力:
| 属性 | 说明 |
|---|---|
Header |
标题内容(在 Statistic 中用作统计项描述) |
HeaderTemplate |
标题数据模板 |
Content |
主内容区域(在 Statistic 中承载格式化后的数值或 StatisticCountUp) |
ContentTemplate |
内容数据模板 |
AtomUI 的扩展设计
| 扩展能力 | 实现方式 | 设计动机 |
|---|---|---|
| 数值格式化 | StatisticUtils.FormatNumber + Precision / GroupSeparator / DecimalSeparator |
自动千分位分隔、小数精度控制,无需手动格式化 |
| 前缀/后缀装饰 | ValuePrefixAddOn / ValueSuffixAddOn 属性 |
支持在数值前后放置图标、单位文本等 |
| 自定义格式化 | Formatter 回调(Func<Statistic, object?, string?>) |
完全自定义数值显示逻辑 |
| 加载骨架屏 | IsLoading + 内置 Skeleton 组件 |
数据加载中时显示占位骨架 |
| 倒计时/计时 | TimerStatistic + DispatcherTimer |
自动刷新剩余时间,支持毫秒级精度 |
| 数值递增动画 | StatisticCountUp + DoubleTransition |
从 0 平滑过渡到目标数值 |
| Design Token 集成 | StatisticToken + 共享 Token 引用 |
标题/内容字体大小、颜色由 Token 驱动 |
功能详解
Statistic(基础统计数值)
Statistic 是最常用的统计数值控件,用于展示一个格式化的数字或文本:
- 通过
Value属性设置原始值(支持int、long、float、double、decimal等数值类型) - 自动通过
StatisticUtils.FormatNumber进行数值格式化(千分位、小数精度) - 如果设置了
Formatter回调,将优先使用自定义格式化逻辑 - 如果直接设置了
Content(例如嵌入StatisticCountUp),则Content优先于Value显示
TimerStatistic(计时器/倒计时)
TimerStatistic 基于目标 DateTime 自动计算并刷新剩余时间:
- 当
Value(目标时间)在未来 → 倒计时模式,显示距目标时间的剩余时长 - 当
Value(目标时间)在过去 → 计时模式,显示从目标时间至今的经过时长 - 当剩余时间归零时触发
CountdownFinished事件,并停止计时器 - 通过
Format属性控制时间显示格式(使用 .NETTimeSpan格式字符串) - 通过
RefreshDuration属性控制刷新间隔(默认 10ms) - 支持
Formatter回调完全自定义时间文本
StatisticCountUp(数值递增动画)
StatisticCountUp 实现了从 0 到目标值的平滑递增动画:
- 通过
EndValue属性设置目标数值 - 控件加载时自动启动动画(
OnLoaded→ 将AnimatingValue设为EndValue) - 动画使用
DoubleTransition+ExponentialEaseOut缓动曲线 - 动画时长由
SharedToken.MotionDurationVerySlow控制 - 可嵌入
Statistic.Content中,继承 Statistic 的标题和样式
加载骨架屏
当 IsLoading = true 时,数值区域会被 Skeleton 组件替换为加载占位骨架。标题仍然正常显示。加载态下的 RootLayout 间距会从 SpacingXXS 增大到 Spacing,给骨架屏更多视觉空间。
与 Ant Design 规范的对齐程度
| 特性 | Ant Design (React) | AtomUI (Avalonia) | 对齐情况 |
|---|---|---|---|
| 标题 + 数值结构 | ✅ title + value |
✅ Header + Value / Content |
✅ 完全对齐 |
前缀 prefix |
✅ ReactNode | ✅ ValuePrefixAddOn(支持图标和文本) |
✅ 完全对齐 |
后缀 suffix |
✅ ReactNode | ✅ ValueSuffixAddOn(支持图标和文本) |
✅ 完全对齐 |
格式化 formatter |
✅ 函数 | ✅ Formatter 委托 |
✅ 完全对齐 |
数值精度 precision |
✅ 数字 | ✅ Precision 属性 |
✅ 完全对齐 |
千分位分隔 groupSeparator |
✅ 字符串 | ✅ GroupSeparator 属性 |
✅ 完全对齐 |
小数分隔符 decimalSeparator |
✅ 字符串 | ✅ DecimalSeparator 属性 |
✅ 完全对齐 |
加载中 loading |
✅ 布尔 | ✅ IsLoading(使用 Skeleton 骨架屏) |
✅ 完全对齐 |
倒计时 Countdown |
✅ 独立组件 | ✅ TimerStatistic |
✅ 完全对齐 |
倒计时格式 format |
✅ dayjs 格式 | ✅ Format(.NET TimeSpan 格式) |
⚠️ 格式语法不同,功能一致 |
倒计时完成事件 onFinish |
✅ 回调 | ✅ CountdownFinished 事件 |
✅ 完全对齐 |
数值动画 countUp |
✅ 需配合第三方库 | ✅ StatisticCountUp 内置支持 |
✅ 对齐(AtomUI 内置实现) |
继承关系
Avalonia.Controls.Primitives.TemplatedControl
└── Avalonia.Controls.Primitives.HeaderedContentControl
└── AtomUI.Desktop.Controls.AbstractStatistic (抽象基类)
├── AtomUI.Desktop.Controls.Statistic (基础统计数值)
└── AtomUI.Desktop.Controls.TimerStatistic (计时器/倒计时)
Avalonia.Controls.Primitives.TemplatedControl
└── AtomUI.Desktop.Controls.StatisticCountUp (数值递增动画)
各层级职责划分:
| 层级 | 提供的能力 |
|---|---|
HeaderedContentControl |
标题 + 内容的双区域结构、Header / HeaderTemplate / Content / ContentTemplate |
AbstractStatistic |
数值格式化参数(DecimalSeparator / GroupSeparator / Precision)、前缀/后缀(ValuePrefixAddOn / ValueSuffixAddOn)、内容样式(ContentForeground / ContentFontSize)、加载状态(IsLoading)、Design Token 注册 |
Statistic |
Value 属性、Formatter 自定义格式化、EffectiveValue 内部计算、与 StatisticCountUp 的集成 |
TimerStatistic |
基于 DateTime 的自动计时、DispatcherTimer 刷新、Format 时间格式、RefreshDuration 刷新间隔、CountdownFinished 事件 |
StatisticCountUp |
EndValue 目标值、AnimatingValue 动画值、DoubleTransition 递增动画、ExponentialEaseOut 缓动 |
注意:Statistic 家族的所有控件均直接定义在
AtomUI.Desktop.Controls中,没有对应的AtomUI.Controls设备无关基类。
源码位置
| 层级 | 文件路径 | 说明 |
|---|---|---|
| 抽象基类 | src/AtomUI.Desktop.Controls/Statistic/AbstractStatistic.cs |
共享的属性、模板逻辑 |
| 基础统计 | src/AtomUI.Desktop.Controls/Statistic/Statistic.cs |
Statistic 实现 |
| 数值动画 | src/AtomUI.Desktop.Controls/Statistic/StatisticCountUp.cs |
StatisticCountUp 实现 |
| 计时器 | src/AtomUI.Desktop.Controls/Statistic/TimerStatistic.cs |
TimerStatistic 实现 |
| 工具类 | src/AtomUI.Desktop.Controls/Statistic/StatisticUtils.cs |
数值格式化工具 |
| Token 定义 | src/AtomUI.Desktop.Controls/Statistic/StatisticToken.cs |
组件级 Design Token |
| 基类主题 | src/AtomUI.Desktop.Controls/Statistic/Themes/AbstractStatisticTheme.axaml |
AbstractStatistic 模板 |
| 统计主题 | src/AtomUI.Desktop.Controls/Statistic/Themes/StatisticTheme.axaml |
Statistic 主题 |
| 计时主题 | src/AtomUI.Desktop.Controls/Statistic/Themes/TimerStatisticTheme.axaml |
TimerStatistic 主题 |
| 动画主题 | src/AtomUI.Desktop.Controls/Statistic/Themes/StatisticCountUpTheme.axaml |
StatisticCountUp 主题 |
| 注册文件 | src/AtomUI.Desktop.Controls/Statistic/Themes/StatisticThemes.axaml |
主题注册 |
| Gallery 示例 | controlgallery/AtomUIGallery/ShowCases/Views/DataDisplay/StatisticShowCase.axaml |
使用范例 |
模板结构
AbstractStatistic / Statistic 模板
Border#Frame (Background, CornerRadius)
└── StackPanel#RootLayout (垂直排列)
├── ContentPresenter#HeaderPresenter ← 标题展示器(当 Header 非 null 时可见)
└── Skeleton (IsLoading 控制骨架屏)
└── StackPanel#ContentLayout (水平排列)
├── ContentPresenter#ValuePrefixAddOn ← 前缀展示器(图标/文本)
├── ContentPresenter#ContentPresenter ← 主内容(格式化后的数值或 StatisticCountUp)
└── ContentPresenter#ValueSuffixAddOn ← 后缀展示器(单位/文本)
TimerStatistic 模板
TimerStatistic 使用了独立的模板(基于 AbstractStatisticTheme),结构与 Statistic 类似,区别在于 ContentPresenter 绑定的是 RemainingTimeText 而非 Content。
StatisticCountUp 模板
TextBlock (Text = FormattedValue)
StatisticCountUp 的模板非常简洁,仅包含一个绑定 FormattedValue 的 TextBlock。动画效果完全通过 AnimatingValue 属性的 DoubleTransition 实现。