You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 04:50:13