Angular Material 2: Jerky Animation of Progress Bars

I am currently developing a page using Angular that includes multiple progress bars indicating the progress made for actions that have specific durations. My goal is to utilize the Angular Material progress bar to create a seamless animation from start time to end time. I have implemented a method where I update the percentage of completion every 50ms and assign this value to the progress bar, as demonstrated in the code snippet below:

const start = new Date().getTime();
const source = timer(0, 50);
const subscribe = source.subscribe(() => {
  const time = new Date().getTime();
  if (time - start > length) {
    subscribe.unsubscribe();
  }

  this.progressValue = 100 * (time - start) / length;
});

Here is the HTML code for the progress bar itself:

<mat-progress-bar mode="determinant" [value]="progressValue"></mat-progress-bar>

However, the progression of the progress bar appears choppy. Are there any alternative methods to achieve a smoother transition? Since the duration of the process is known each time, I believe achieving a smooth progression for that specified time should be straightforward. Thank you!

Answer №1

Here is my solution:

Below is the HTML code snippet:

<mat-progress-bar color="accent" mode="determinate" [value]="uploadPercentage$ | async"></mat-progress-bar>

This is how the component looks like:

@ViewChild(MatProgressBar) progressBar: MatProgressBar;
uploadPercentage$: Observable<number>;
uploadProgress$: Subject<HttpProgressEvent> = new Subject<HttpProgressEvent>();

ngAfterViewInit(): void {
    // Wait for the animation to end before changing value
    this.uploadPercentage$ = this.progressBar.animationEnd
      .pipe(
        startWith({
          value: 0
        }),
        switchMap((animationState: ProgressAnimationEnd) => this.uploadProgress$
          .pipe(
            map((progress: HttpProgressEvent): number => this.progressToPercents(progress)),
            distinctUntilChanged((val: number) => animationState.value !== val)
          )
        ),
      );
  }

Answer №2

I have successfully implemented a custom progress bar using Angular Animations. The transition is seamless and resembles the appearance of mat-progress-bar:

1) Incorporate Animations into your component:

  selector: 'app-loading',
  templateUrl: './loading.component.html',
  styleUrls: ['./loading.component.scss'],
  animations: [
    trigger('loading', [
      state('start',
        style({
          width: '0%'
        })
      ),
      state('end',
        style({
          width: '100%'
        })),

      transition('start => end', [
        animate(2000)
      ]),
    ])
  ]
})

2) Set a timer to trigger the animation. I close the dialog once the progress is complete:

duration: number = 2 * 100;
step = 100;
add_step = 10;
progress = 0;


ngOnInit() {
    const interval = setInterval(() => {
      if (this.progress < this.duration) {
        this.progress += this.add_step ;
      } else {
        clearInterval(interval);
        this.dialogRef.close();
      }
    }, this.step);
  }

3) Implement it in the HTML:

<div style="background-color: #ff7a7a;height: 4px;width: 100%;">
        <div style="background-color: #760000;height: 4px;"
             [@loading]="progress === 0 ? 'start':'end'">
        </div>
</div>

Answer №3

Here is a simplified version of Nodarii's answer:

HTML:

<mat-progress-bar color="accent" mode="determinate" [value]="uploadPercentage$ | async"></mat-progress-bar>

Component:

@ViewChild(MatProgressBar) progressBar: MatProgressBar;
uploadPercentage$: Observable<number>;

ngAfterViewInit(): void {
    this.uploadPercentage$ = this.progressBar.animationEnd.pipe(
        startWith(0),
        delay(0),
        map(() => this.yourPercentage)
    );
}

Let Angular Material handle the animation for you ;)

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The ngTemplateOutletContext context source is not defined

That snippet of code was functional with Angular 2, and possibly even with versions earlier than Angular 4.3.6. Currently, the gradingKey object is undefined within the display or edit template section. However, it is not undefined in the getTemplate(gra ...

Is the Angular Tutorial's use of the In-memory Web API conforming to the appropriate PUT semantics?

As I was going through the Angular tutorial, I came across the utilization of the In-memory Web API. Everything seems fine except for the segment of code within the PUT heroes method that makes me a bit uneasy. Take a look at it: private heroesUrl = &apo ...

Angular/Bootstrap Card Components

I am in the process of developing a single-page website that showcases information about different episodes. I currently have a mongoDB set up where each of the 50 episodes is stored as a separate object. Using Bootstrap 4, I am encountering difficulty in ...

Angular Form Validations - input values must not match the initial values

These are my current reactive form validations: ngOnInit(): void { this.userForm = this.formBuilder.group({ status: {checked: this.selectedUser.status == 1}, username: [this.selectedUser.username, [Validators.required, Validators.minLeng ...

The field '_id' is not present in the type Pick

I'm working on a project using Next.js and attempting to query MongoDB with TypeScript and mongoose, but I keep encountering a type error. types.d.ts type dbPost = { _id: string user: { uid: string name: string avatar: string } po ...

Implement the properties encapsulation design pattern

In need of a method to control document activation logic, where activating a document involves adding it to a list of activeDocuments and setting a flag to true. Direct access to the isActive property should be prohibited. class DocumentService { pr ...

Populate an array of objects with time values up to 24 hours ago

Here is an array of objects that I am working with: {x: "14:33", y: 0} {x: "14:34", y: 0} {x: "14:35", y: 1} {x: "14:36", y: 1} {x: "14:37", y: 0} {x: "15:33", y: 0} {x: "15:34", y: 0} {x: "15:35", y: 1} {x: "15:36", y: 1} {x: "15:37", y: 0} Let's c ...

Angular problem: Cannot connect to 'formGroup' as it is not a recognized property of 'form'

Struggling to set up a simple form in Angular consisting of a label and an input field. Despite following suggestions to import FormsModule and ReactiveFormsModule, I'm still encountering errors as mentioned numerous times on StackOverflow. Here&apos ...

Ways to implement logging in an NPM package without the need for a specific logging library

Currently, I am in the process of developing a company npm package using TypeScript and transferring existing code to it. Within the existing code, there are instances of console.log, console.warn, and console.error statements, as shown below: try { c ...

Creating motion in recently added elements using varied keyframe settings

I'm currently working on a simple animation project. The goal is to create a circle that appears and moves upwards when you click inside the blue container. I managed to find out how to incorporate JavaScript values into keyframes, but the issue is th ...

nginx error when trying to navigate angular routes

My Angular app is hosted in GKE using nginx with the following configuration: location / { root /usr/share/nginx/www; try_files $uri $uri/ /index.html } When I access http://ipaddress/field, it loads the application at http://ipaddress ...

In Angular code, the foreach loop jumps to the next function before completing each iteration of the loop

private processArray(evts: Event[]): Promise<void> { var auditsvc = this.auditSvc; var t = this; if (!evts || evts.length == 0) { return; } let objArr: any[] = []; evts.forEach(function (inpEvt) { auditsvc.getAuditDetails(inpEv ...

There was an issue encountered when executing Angular in Cypress: The module '@angular/compiler' is not found

While conducting Cypress E2E testing, Angular appears to not be running properly. We encountered the following Angular error after migrating to version 18: The error is originating from your test code, not Cypress. > The injectable 'PlatformNaviga ...

In Typescript, object strings can be enforced to be used from the parent object similar to

I am currently developing an API wrapper for a lower level library that utilizes enums to map human readable keys to internal values. In order to enhance security, I want to only use the enum keys and not the underlying values in any logging or other funct ...

Dynamic property name construction in typescript: dynamically creating property names on types

Although this may seem like a simple TS issue, I'm struggling to find the correct syntax. Consider this type: type MyType = { prop1: string; prop2: string; } Now, within a function, I have a variable of type MyType. However, I need to dynamic ...

Trigger the component to emit an event once all validators have been cleared

I have developed a unique custom input element that showcases its label when a required constraint is present (calculated in the OnInit method). @Component({ selector: 'custom-input', template: `<div *ngIf="isMandatory()">Mand ...

Angular's NavigationEnd event is triggered prior to the resolution of data for the subsequent page

Here is what I am currently working on: ngOnInit() { this.router.events.subscribe((evt) => { if (!(evt instanceof NavigationEnd)) { return; } window.scrollTo(0, 0); }); I am using this code to ensure that the page scrolls back to the top e ...

Angular5 encountered a problem with the ngx-bootstrap DatePicker when handling DateTime objects

I currently have a SQL Server database field called 'JoiningDate' with the type of date (no time included). To collect input from users, I am utilizing the ngx-bootstrap datepicker. However, I am encountering an issue where the datepicker convert ...

What is the proper way to effectively utilize modules in Angular?

As a beginner in Angular, I've been debating whether it's better to have one module for each component or to work without custom modules. In the past, I typically created a component and passed it to declarations in app.module.ts. However, I rece ...

Tips for ensuring session token verification remains intact upon reloading

I am currently in the process of developing a website using the Next.js framework and I am seeking advice on how to prevent the reload effect that occurs when transitioning from the login page back to the main page for just a fraction of a second. Below i ...