typescript - Angular 5 fryser UI när man använder ngx-pica Image resizer


Jag försöker skapa en bilduppladdningsfunktion för min Angular 5-webbplats. Den använder ngx-Pica för att ändra storlek på bilderna på klientsidan, men jag har problem med att användargränssnittet fryser medan resize-tjänsten anropas och jag behöver några idéer om hur man kan stoppa att det fryser.

Bildstorlekarna är: (alla tillagda samtidigt)

  • 2,6 MB
  • 1,7 MB
  • 3,46 MB

Jag förstår inte vad som orsakar frysen, all hjälp skulle uppskattas.

Saker jag har provat

Jag har försökt ta bort changeDetectorRef.detectChanges() bara för att se om det stoppar UI från att frysa, det gjorde det inte

Att lägga till bilderna utan att ändra storlek på dem stoppar frysningsproblemet (genom att ta bort anropet till this._ngxPicaService.resizeImage)

Jag försökte granska källkoden men kunde inte hitta något som är uppenbart

Jag tillhandahåller storleksändringsfunktionen så att jag inte behöver begränsa storleken på bilder som användaren laddar upp, men uppenbarligen är ett fruset gränssnitt inte heller acceptabelt

import { Component, ViewEncapsulation, ChangeDetectorRef } from '@angular/core';

import { NgxPicaService, NgxPicaErrorInterface, NgxPicaResizeOptionsInterface, NgxPicaImageService } from 'ngx-pica';
import { AspectRatioOptions } from 'ngx-pica/src/ngx-pica-resize-options.interface';

@Component({
  selector: 'az-multiple-image-uploader',
  encapsulation: ViewEncapsulation.None,
  templateUrl: './multiple-image-uploader.component.html',
  styleUrls: ['./multiple-image-uploader.component.scss']
})
export class MultipleImageUploaderComponent { 
    public images: File[] = [];

    constructor(
        private _changeDetectorRef: ChangeDetectorRef, 
        private _ngxPicaService: NgxPicaService, 
        private _ngxPicaImageService: NgxPicaImageService 
    ) { }    

    fileChange(input){
        this.handleFiles(input.files);
    }

    private addLoadingAnimations(numberToAdd: number): void {
        var spinner = require("assets/img/Spinner.svg");

        for(var i =0; i < numberToAdd; i++)
        {
            this.images.push(spinner);
        }
    }

    public handleFiles(files: any) {
        var listLength = this.images.length;
        this.addLoadingAnimations(files.length);

        var width = 1024;
        var height = 683;

        for(var index = 0; index < files.length; index++){
            this._ngxPicaService.resizeImage(files[index], width, height, new ImageResizeOptions())
                .subscribe((imageResized: File) => {
                    let reader: FileReader = new FileReader();

                    reader.addEventListener('load', (event: any) => {
                        this.images.splice(listLength, 1);
                        this.images[listLength] = event.target.result;
                        listLength += 1;
                        this._changeDetectorRef.detectChanges();
                    }, false);

                    reader.readAsDataURL(imageResized);

            }, (err: NgxPicaErrorInterface) => {
                throw err.err;
            });
        }
    }

    removeImage(index):void{
        this.images.splice(index, 1);
    }
}

export class ImageResizeOptions implements NgxPicaResizeOptionsInterface
{
  aspectRatio = new ImageAspectRatioOptions(true);
}

export class ImageAspectRatioOptions implements AspectRatioOptions {
  keepAspectRatio: boolean;
  forceMinDimensions?: boolean;

  constructor(keepAspectRatio: boolean, forceMinDimensions?: boolean) {
    this.keepAspectRatio = keepAspectRatio;
    this.forceMinDimensions = forceMinDimensions;
  }
}


<div class="col-8 mx-auto">
    <input type="file" multiple (change)="fileChange(input)" #input class="m-img-upload-btn"/>
    <button class="btn btn-success btn-block" type="button">
        <i class="fa fa-upload"></i> Images...
    </button>
</div>

<div class="card images-container">
    <div *ngFor="let image of images; let i=index;" class="m-image-wrapper">
        <i class="fa fa-times m-delete-img" (click)="removeImage(i)"></i>
        <img [src]="image"> 
    </div> 
</div>

Svar #1

Svaret på att stoppa ett användargränssnitt från att frysa är webbarbetare.

Uppgiften jag försökte göra tar lång tid och alla långvariga beräkningar kommer att få användargränssnittet att frysa.

I Angular finns ett trevligt litet paket som heter https://www.npmjs.com/package/angular2-web-worker som hjälper dig att implementera webbworkers