Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular material progress spinner

Does anyone know how to show the incomplete portion in material progress spinner when the mode is determinate.Now I'm getting like this
image1.

but I want like this image2

like image 418
Priyanka Avatar asked Sep 12 '18 06:09

Priyanka


1 Answers

This can be done but it's mostly a hack. The idea is to use a div with a border that matches the spinner and place it behind the spinner.

Progress spinner with background

Example on StackBlitz

<div class="spinner-container">
    <div class="spinner-background">{{spinner.value}}%</div>
    <mat-progress-spinner #spinner
        color="primary"
        mode="determinate"
        value="75">
    </mat-progress-spinner>
</div>

The trick is the div styling, which needs to be sized and positioned to match your spinner exactly:

.spinner-container {
    position: relative;
}
.spinner-background {
    position: absolute;
    width: 80px;
    height: 80px;
    line-height: 80px;
    text-align: center;
    overflow: hidden;
    border-color: rgba(103, 58, 183, 0.12);
    border-radius: 50%;
    border-style: solid;
    border-width: 10px;
}

EDIT:

I built a simple wrapper component for this that handles sizing and theme coloring automatically:

StackBlitz

spinner-container.ts:

import { coerceNumberProperty } from '@angular/cdk/coercion';
import { AfterViewInit, Component, ElementRef, Input, SimpleChanges } from '@angular/core';
import { CanColor, mixinColor, ThemePalette } from '@angular/material/core';

const BASE_SIZE = 100;
const BASE_STROKE_WIDTH = 10;
export class SpinnerContainerBase {
  constructor(public _elementRef: ElementRef) { }
}
export const _SpinnerContainerMixinBase = mixinColor(SpinnerContainerBase, 'primary');

/**
 * @title Progress spinner container for spinner circle background and value display
 */
@Component({
  selector: 'spinner-container',
  templateUrl: 'spinner-container.html',
  styleUrls: ['spinner-container.scss'],
  host: {
    'class': 'spinner-container',
    '[style.width.px]': 'diameter',
    '[style.height.px]': 'diameter',
    '[style.line-height.px]': 'diameter'
  }
})
export class SpinnerContainer extends _SpinnerContainerMixinBase implements AfterViewInit, CanColor {

  constructor(public _elementRef: ElementRef) {
    super(_elementRef);
  }

  @Input() color: ThemePalette = 'primary';

  @Input()
  get diameter(): number { return this._diameter; }
  set diameter(size: number) {
    this._diameter = coerceNumberProperty(size);
  }
  private _diameter: number = BASE_SIZE;

  @Input() displayWith: (number) => string | number;

  @Input()
  get strokeWidth() { return this._strokeWidth; }
  set strokeWidth(newValue: number) {
    if (newValue) {
      this._strokeWidth = Math.min(this.diameter / 2, coerceNumberProperty(newValue));
      if (this._spinnerBackgroundElement) {
        this._spinnerBackgroundElement.style.borderWidth = this.strokeWidth + 'px';
      }
    }
  }
  private _strokeWidth: number = BASE_STROKE_WIDTH;

  @Input()
  get value(): number { return this._value; }
  set value(newValue: number) {
    this._value = Math.max(0, Math.min(100, coerceNumberProperty(newValue)));
  }
  private _value: number = 0;

  private _spinnerBackgroundElement: HTMLElement;

  ngAfterViewInit() {
    this._spinnerBackgroundElement = this._elementRef.nativeElement.querySelector('.spinner-background');
    this._spinnerBackgroundElement.style.borderWidth = this.strokeWidth + 'px';
  }
}

spinner-container.html

<div class="spinner-value" *ngIf="displayWith">{{displayWith(value)}}</div>
<div class="spinner-background"></div>
<mat-progress-spinner 
    [color]="color" 
    [diameter]="diameter" 
    mode="determinate" 
    [strokeWidth]="strokeWidth" 
    [value]="value">
</mat-progress-spinner>

spinner-container.scss

:host {
    display: block;
    position: relative;

    .spinner-value, .spinner-background {
        position: absolute;
        width: inherit;
        height: inherit;
    }

    .spinner-value {
        text-align: center;
        overflow: hidden;
    }

    .spinner-background {
        opacity: .12;
        box-sizing: border-box;
        border-radius: 50%;
        border-style: solid;
    }
}

_spinner-container-theme.scss

@mixin spinner-container-theme($theme) {

    $primary: map-get($theme, primary);
    $accent: map-get($theme, accent);
    $warn: map-get($theme, warn);

    .spinner-background {
        .spinner-container.mat-primary & {
            color: mat-color($primary);
        }
        .spinner-container.mat-accent & {
            color: mat-color($accent);
        }
        .spinner-container.mat-warn & {
            color: mat-color($warn);
        }
    }
}
like image 105
G. Tranter Avatar answered Oct 10 '22 19:10

G. Tranter