Angular Material Progress Spinner 完整 API 指南:@angular/material_progress-spinner公共接口深度解析
【免费下载链接】componentsComponent infrastructure and Material Design components for Angular项目地址: https://gitcode.com/GitHub_Trending/co/components
本文以@angular/material_progress-spinner的公共 API 报告(goldens/material/progress-spinner/index.api.md)为核心,逐一解读MatProgressSpinner组件、MAT_PROGRESS_SPINNER_DEFAULT_OPTIONS注入令牌、ProgressSpinnerMode类型与MatSpinner别名等全部公开接口,并结合本仓库中该组件的源码实现、模板与测试用例,说明每个输入属性在底层是如何被解析、钳制与渲染的,帮助你在实际项目中正确配置圆形进度指示器并规避无障碍与动画误区。
从 API 报告看组件的完整公共面
API 报告由 API Extractor 自动生成,是组件公共 API 的“权威清单”。它精确列出了@angular/material_progress-spinner包对外暴露的全部符号,包括两个类、一个接口、一个类型别名、一个注入令牌与一个弃用别名:
| 公开符号 | 类型 | 说明 |
|---|---|---|
MatProgressSpinner | 类(组件) | 圆形进度指示器,选择器mat-progress-spinner, mat-spinner |
MatProgressSpinnerModule | 类(NgModule) | 导入即获得组件能力 |
MatProgressSpinnerDefaultOptions | 接口 | 可通过依赖注入覆盖的默认配置 |
MAT_PROGRESS_SPINNER_DEFAULT_OPTIONS | InjectionToken | 用于提供全局默认配置的令牌 |
ProgressSpinnerMode | 类型别名 | 'determinate' \| 'indeterminate' |
MatSpinner | 常量(弃用) | MatProgressSpinner的历史别名 |
报告还透露了几个实现细节:组件声明了 5 个输入(color、mode、value、diameter、strokeWidth),且diameter、strokeWidth、value三个数值输入通过ngAcceptInputType静态字段接收任意类型(由 Angular 的numberAttribute转换器处理);同时组件内部维护了_circleRadius()、_strokeCircumference()、_strokeDashOffset()、_viewBox()等 SVG 几何计算辅助方法。下文将结合源码逐一展开。
快速上手:两种组件形态
MatProgressSpinner的宿主选择器同时注册了mat-progress-spinner与mat-spinner两个名称,见 progress-spinner.ts 中的selector字段。二者的关系在构造函数中被固定:
this.mode = element.nodeName.toLowerCase() === 'mat-spinner' ? 'indeterminate' : 'determinate';即<mat-spinner>是<mat-progress-spinner mode="indeterminate">的简写形式。引用该组件只需导入模块:
import {MatProgressSpinnerModule} from '@angular/material/progress-spinner'; @NgModule({ imports: [MatProgressSpinnerModule], }) export class AppModule {}从模块源码(progress-spinner-module.ts)可以看到,模块同时导出了MatProgressSpinner、MatSpinner以及来自@angular/cdk/bidi的BidiModule——后者对应 API 报告中模块声明里对i2.BidiModule的依赖,用于在 RTL 环境下正确处理圆形指示的方向。
进度模式:determinate 与 indeterminate
ProgressSpinnerMode在 progress-spinner.ts 中定义为联合类型:
export type ProgressSpinnerMode = 'determinate' | 'indeterminate';两种模式的语义与行为如下(与组件文档 progress-spinner.md 一致):
| 模式 | 语义 | value行为 |
|---|---|---|
determinate | 标准进度指示,从 0% 填充到 100% | 生效,决定弧线长短 |
indeterminate | 表示“正在发生某事”,不传达具体进度 | 被忽略,始终返回 0 |
默认模式是determinate。这一点既有文档佐证(“The default mode is 'determinate'”),也有测试佐证:在 progress-spinner.spec.ts 中,"should apply a mode of 'determinate' if no mode is provided" 用例断言未传mode时组件实例的mode为'determinate'。
关于value与模式的关系,源码中的 getter 揭示了一个容易被忽略的细节:
get value(): number { return this.mode === 'determinate' ? this._value : 0; } set value(v: number) { this._value = Math.max(0, Math.min(100, v || 0)); }即:输入值始终被钳制在 0~100 之间,且内部值会被保留。切换到 indeterminate 模式时value对外返回 0,但切回 determinate 后原先设置的值会恢复。测试用例 "should retain the value if it updates while indeterminate"(progress-spinner.spec.ts)完整验证了这一保留语义。
用法示例:
<!-- determinate:value 决定进度 --> <mat-progress-spinner mode="determinate" value="60"></mat-progress-spinner> <!-- indeterminate:无需 value --> <mat-progress-spinner mode="indeterminate"></mat-progress-spinner> <!-- 简写别名 --> <mat-spinner></mat-spinner>尺寸与描边:diameter 与 strokeWidth
diameter决定整个圆形的像素直径,直接反映为宿主元素的宽高;strokeWidth决定圆弧描边的粗细。二者在组件构造时都有内置基准值(progress-spinner.ts):
const BASE_SIZE = 100; // 默认直径 100px const BASE_STROKE_WIDTH = 10; // 基准描边宽 10px两个输入的默认与联动逻辑如下:
diameter默认值为BASE_SIZE(100),通过numberAttribute转换器接收数字或数字字符串;strokeWidth的 getter 在未显式赋值时回退为diameter / 10(progress-spinner.ts),即默认保持“直径的十分之一”这一比例,便于随尺寸等比缩放;- 宿主元素上通过
[style.width.px]、[style.height.px]同步直径,并额外设置 CSS 自定义属性--mat-progress-spinner-size与--mat-progress-spinner-active-indicator-width供内部样式使用(见组件host元数据)。
典型用法:
<!-- 直径 50px,描边默认 5px --> <mat-progress-spinner diameter="50"></mat-progress-spinner> <!-- 显式指定描边宽度 --> <mat-progress-spinner diameter="80" strokeWidth="8" value="30"></mat-progress-spinner>底层的 SVG 几何计算
API 报告列出的_circleRadius()、_strokeCircumference()、_strokeDashOffset()、_viewBox()与_circleStrokeWidth()是模板渲染的关键:模板(progress-spinner.html)中的<circle>元素依赖这些方法计算半径、周长与虚线偏移。
_circleRadius():(diameter - BASE_STROKE_WIDTH) / 2,即半径在直径基础上扣除基准描边宽度的一半,防止圆弧溢出;_strokeCircumference():2 * Math.PI * radius,即圆的周长,用作stroke-dasharray;_strokeDashOffset():仅在 determinate 模式下返回circumference * (100 - value) / 100,通过“减少可见弧长”来表现进度百分比;indeterminate 模式下返回null,由 CSS 动画接管旋转;_viewBox():0 0 (2r + strokeWidth) (2r + strokeWidth),保证 SVG 视口恰好容纳圆与描边。
也就是说,进度弧线并非“按角度截取”,而是利用 SVGstroke-dashoffset技术,把圆周按百分比“遮罩”,这与 MDC circular progress 的实现保持一致。
全局默认配置:MAT_PROGRESS_SPINNER_DEFAULT_OPTIONS
API 报告给出了MatProgressSpinnerDefaultOptions接口的完整字段:
export interface MatProgressSpinnerDefaultOptions { color?: ThemePalette; diameter?: number; _forceAnimations?: boolean; strokeWidth?: number; }对应的注入令牌在 progress-spinner.ts 中定义,默认工厂只提供{diameter: BASE_SIZE}:
export const MAT_PROGRESS_SPINNER_DEFAULT_OPTIONS = new InjectionToken<MatProgressSpinnerDefaultOptions>('mat-progress-spinner-default-options', { providedIn: 'root', factory: () => ({diameter: BASE_SIZE}), });在应用根或特性模块中覆盖该令牌,即可为全站所有mat-progress-spinner提供统一默认值,例如统一缩小到 40px:
import {MAT_PROGRESS_SPINNER_DEFAULT_OPTIONS} from '@angular/material/progress-spinner'; providers: [ { provide: MAT_PROGRESS_SPINNER_DEFAULT_OPTIONS, useValue: {diameter: 40, strokeWidth: 4, color: 'primary'}, }, ]构造函数读取默认值的逻辑(progress-spinner.ts)要点如下:
- 若有
defaults.color,则同时写入当前颜色与_defaultColor(默认主题色为'primary'); - 若有
defaults.diameter、defaults.strokeWidth,则作为初始值应用; - 组件级显式输入会覆盖这些默认值(Angular 输入绑定在构造后生效)。
_forceAnimations与动画降级
接口中以下划线开头的_forceAnimations属于内部半公开字段,它控制动画是否“强制启用”。构造函数中:
const animationsState = _getAnimationsState(); this._noopAnimations = animationsState === 'di-disabled' && !!defaults && !defaults._forceAnimations;即:当 Angular 动画状态为 disabled 时,除非显式设置_forceAnimations: true,否则组件会加上_mat-animation-noopable类并关闭动画;而当系统处于reduced-motion(减弱动态效果)偏好时,组件会追加mat-progress-spinner-reduced-motion类以尊重用户偏好。这套逻辑同时保障了性能敏感场景(关闭动画)与无障碍场景(减弱动画)。
主题色:color 输入与 M2/M3 差异
color输入接受ThemePalette(通常为'primary' | 'accent' | 'warn'及 null/undefined),getter 的逻辑是this._color || this._defaultColor,未指定时回退到默认主题色'primary'。宿主元素通过[class]='"mat-" + color'动态挂载mat-primary等类名(见组件host元数据)。
需要特别留意 API 报告与源码注释中的约束:color仅在 M2 主题下生效,在 M3 主题下无效果。主题样式文件 _progress-spinner-theme.scss 证实了这一设计——其colormixin 针对非 M3 主题额外为.mat-accent、.mat-warn生成色板 token,而 M3 主题则改用 color-variant 机制。因此:
- M2 主题:直接使用
color="accent"等即可; - M3 主题:请改用主题的 color-variant 参数(
@include mat.progress-spinner-theme($theme, $color-variant: ...))或设计令牌定制颜色。
无障碍实现:完整的 ARIA progressbar 模式
API 报告中虽然没有直接列出 ARIA 属性,但宿主元数据(progress-spinner.ts)与组件文档(progress-spinner.md)给出了完整的无障碍契约:
host: { 'role': 'progressbar', 'tabindex': '-1', '[attr.aria-valuemin]': '0', '[attr.aria-valuemax]': '100', '[attr.aria-valuenow]': 'mode === "determinate" ? value : null', '[attr.mode]': 'mode', }- 组件根元素自带
role="progressbar",并设置aria-valuemin="0"、aria-valuemax="100",官方建议不要修改这两个值,以免与某些辅助技术不兼容; - determinate 模式下
aria-valuenow实时反映当前进度;indeterminate 模式不输出aria-valuenow(辅助技术会据此识别为“进行中但无具体进度”); tabindex="-1"让屏幕阅读器可以读取aria-label,不过组件文档特别提示 JAWS 在 Firefox 上存在已知问题;- 每个 spinner 都必须通过
aria-label或aria-labelledby提供可访问标签,例如<mat-progress-spinner aria-label="加载中" mode="indeterminate"></mat-progress-spinner>; - 模板中所有圆形图形容器均带
aria-hidden="true"(见 progress-spinner.html),避免重复朗读,这是为兼容 ChromeVox 而做的处理。
组件测试 Harness:MatProgressSpinnerHarness
对于需要编写组件测试的场景,本仓库在 testing/progress-spinner-harness.ts 提供了官方测试 Harness:
export class MatProgressSpinnerHarness extends ComponentHarness { static hostSelector = '.mat-mdc-progress-spinner'; static with<T extends MatProgressSpinnerHarness>( this: ComponentHarnessConstructor<T>, options: ProgressSpinnerHarnessFilters = {}, ): HarnessPredicate<T> {...} /** Gets the progress spinner's value. */ async getValue(): Promise<number | null> {...} /** Gets the progress spinner's mode. */ async getMode(): Promise<ProgressSpinnerMode> {...} }- 宿主选择器为
.mat-mdc-progress-spinner(与组件host中的class对应); getValue()读取aria-valuenow属性并使用coerceNumberProperty转为数字,无属性时返回null;getMode()直接读取mode属性;- 过滤条件
ProgressSpinnerHarnessFilters继承自BaseHarnessFilters(progress-spinner-harness-filters.ts),目前没有额外过滤字段,但保留了with()的扩展入口。
在测试中使用:
import {MatProgressSpinnerHarness} from '@angular/material/progress-spinner/testing'; const spinner = await loader.getHarness(MatProgressSpinnerHarness); expect(await spinner.getMode()).toBe('indeterminate');弃用说明:MatSpinner 别名
API 报告将MatSpinner标记为@public @deprecated:
/** * @deprecated Import Progress Spinner instead. Note that the * `mat-spinner` selector isn't deprecated. * @breaking-change 16.0.0 */ export const MatSpinner = MatProgressSpinner;需要区分两件事:被弃用的是MatSpinner这个 TypeScript 符号(请直接导入MatProgressSpinner),而<mat-spinner>选择器本身并未弃用,仍可放心在模板中使用。此外MatProgressSpinnerModule仍同时导出二者,现有基于MatSpinner的代码在模块层面不受影响。
从 API 到实践:一个完整的综合示例
将以上 API 组合起来,一个覆盖全局默认值、尺寸定制与无障碍标签的完整示例:
<mat-progress-spinner mode="determinate" value="{{uploadProgress}}" diameter="48" strokeWidth="5" color="primary" aria-label="文件上传进度"></mat-progress-spinner>配套的全局默认配置:
import {MAT_PROGRESS_SPINNER_DEFAULT_OPTIONS} from '@angular/material/progress-spinner'; export const SPINNER_DEFAULTS = { provide: MAT_PROGRESS_SPINNER_DEFAULT_OPTIONS, useValue: {diameter: 48, strokeWidth: 5, color: 'primary'}, };小结一下各输入属性的默认值与行为(依据 progress-spinner.ts 与 API 报告):
| 输入 | 默认值 | 说明 |
|---|---|---|
mode | 'determinate'(mat-spinner为'indeterminate') | 进度模式 |
value | 0,钳制在 0~100 | determinate 模式下的进度值,indeterminate 时对外返回 0 |
diameter | 100 | 圆形直径(px),决定宿主宽高 |
strokeWidth | diameter / 10 | 描边宽度(px),未设置时随直径等比缩放 |
color | 'primary' | 主题色,仅 M2 主题生效 |
在集成时请特别核对三点:确认项目使用的是 M2 还是 M3 主题以决定color的用法;为每个 spinner 补齐aria-label;若全局关闭了 Angular 动画,考虑是否需要_forceAnimations恢复指示动画。通过 API 报告 + 源码 + 测试三者互证,MatProgressSpinner的每一个公共接口都有明确的实现落点与可验证的行为,这为团队后续的定制与排查提供了最可靠的依据。
【免费下载链接】componentsComponent infrastructure and Material Design components for Angular项目地址: https://gitcode.com/GitHub_Trending/co/components
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考