如何让Angular Material Progress Spinner的直径响应窗口大小?
Angular Material Progress Spinner 实现响应式直径
要让mat-progress-spinner的diameter属性随窗口大小动态变化,实现相对尺寸,有几种实用的方案:
方案一:监听窗口resize事件计算尺寸
通过Angular的HostListener监听窗口大小变化,动态计算diameter的数值,还可以添加最小/最大值限制避免尺寸异常。
组件代码
import { Component, HostListener, OnInit } from '@angular/core'; @Component({ selector: 'app-responsive-spinner', template: ` <mat-progress-spinner [diameter]="spinnerDiameter"></mat-progress-spinner> ` }) export class ResponsiveSpinnerComponent implements OnInit { spinnerDiameter = 24; ngOnInit() { // 初始化时先计算一次尺寸 this.calculateSpinnerSize(); } @HostListener('window:resize') onWindowResize() { this.calculateSpinnerSize(); } private calculateSpinnerSize() { // 以窗口宽度的5%作为直径,可根据需求调整比例 const calculatedSize = window.innerWidth * 0.05; // 限制最小24px,最大120px this.spinnerDiameter = Math.max(24, Math.min(120, calculatedSize)); } }
方案二:用RxJS实现响应式数据流
利用RxJS监听窗口resize事件,通过async管道自动管理订阅,更符合Angular响应式编程的风格。
组件代码
import { Component } from '@angular/core'; import { fromEvent, map, startWith } from 'rxjs'; @Component({ selector: 'app-responsive-spinner', template: ` <mat-progress-spinner [diameter]="spinnerSize$ | async"></mat-progress-spinner> ` }) export class ResponsiveSpinnerComponent { // 创建监听窗口尺寸的Observable spinnerSize$ = fromEvent(window, 'resize').pipe( startWith(null), // 初始化时触发一次计算 map(() => { const size = window.innerWidth * 0.05; return Math.max(24, Math.min(120, size)); }) ); }
方案三:基于容器大小缩放
如果需要让Spinner随父容器尺寸变化而非窗口,可以用ResizeObserver监听容器大小,通过CSS缩放调整显示尺寸,同时调整strokeWidth保持线条粗细一致。
组件代码
import { Component, ElementRef, OnInit, ViewChild } from '@angular/core'; @Component({ selector: 'app-responsive-spinner', template: ` <div #spinnerContainer class="spinner-container"> <mat-progress-spinner [diameter]="baseDiameter" [strokeWidth]="baseStrokeWidth / scale"> </mat-progress-spinner> </div> `, styles: [` .spinner-container { width: 10vw; /* 容器用相对单位 */ height: 10vw; } `] }) export class ResponsiveSpinnerComponent implements OnInit { @ViewChild('spinnerContainer') spinnerContainer!: ElementRef; baseDiameter = 24; baseStrokeWidth = 2; scale = 1; ngOnInit() { const observer = new ResizeObserver(entries => { const container = entries[0]; // 取容器宽高中的较小值计算缩放比例 const containerSize = Math.min(container.contentRect.width, container.contentRect.height); this.scale = containerSize / this.baseDiameter; // 应用缩放样式 this.spinnerContainer.nativeElement.firstElementChild.style.transform = `scale(${this.scale})`; }); observer.observe(this.spinnerContainer.nativeElement); } }
以上三种方案可以根据实际场景选择:前两种适合基于窗口的全局响应,第三种适合基于容器的局部响应。
内容的提问来源于stack exchange,提问作者LaCodeM
相关产品推荐
相关产品推荐

