typescript - Angular prestandaproblem vid beskärning av bild


Jag använder denna komponent för att beskära bilder som en del av ett ionic/angular8-projekt, men jag får allvarliga prestandaproblem som gör att appen blir oresponsiv ibland, detta visar sig bara när den körs från mobil, desktopversionen visar inga problem, beskärningen fungerar precis som den ska.

När jag gör en prestandaanalys ser jag i vissa fall dessa skräpsamlingar; jag kommer från en Java-värld, och GC är alltid ett prestandaproblem, men har inte hittat mycket om det, men jag tror inte att det är roten till problemet:

Här är ett annat exempel, det verkar vara en fördröjning mellan när användaren interagerar med skärmen och när min interna metod anropas, som du kan se finns det ett Funktionsanrop, men vilken funktion.

Min allmänna kod är nästan samma som på sidan, men jag kommer att dela den här:

Html :

<div class="popup-form-container ion-text-center ion-padding">
<image-cropper
      [imageChangedEvent]="imageChangedEvent"
      [maintainAspectRatio]="true"
      [aspectRatio]="4 / 4"
      format="png"
      (imageCropped)="imageCropped($event)"
      (imageLoaded)="imageLoaded()"
      (cropperReady)="cropperReady()"
      (loadImageFailed)="loadImageFailed()"
  ></image-cropper>
  <ion-button fill="clear" color="danger" (click)="close()">Cancelar</ion-button>
  <ion-button color="green" (click)="save()">Guardar</ion-button>
</div>

Och här kan du se min klass, jag lade till en massa console logs i processen att hitta problemet, och något jag har sett är att när appen fryser och stannar i det långa anropet, finns det ingen output, sedan plötsligt, mycket i rad:

    @Component({
  selector: 'app-crop-image-popover',
  templateUrl: './crop-image-popover.component.html',
  styleUrls: ['./crop-image-popover.component.scss',
              '../../text-area/text-edit-popover/text-edit-popover.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class CropImagePopoverComponent implements OnInit {

  @Input()
  imageChangedEvent: any;

  private croppedImage: any = '';
  private uploader: FileUploader;
  private imageUrl: any;
  private errors: any;

  constructor(private modalCtrl: ModalController,
              private commonSrv: CommonService,
              protected cloudinary: Cloudinary,
              private alertCtrl: AlertController,
              private sysParamsSrv: SystemParamsService,
              private base64: Base64,
              private domSanitizer: DomSanitizer,
              private imageCompress: NgxImageCompressService,
              private changeDetector: ChangeDetectorRef) {
    // Inicializamos el compoente de carga de archivos

  }

  ngOnInit() {}

  imageCropped(event: ImageCroppedEvent) {
    console.log('cropped');
    this.croppedImage = event.base64;
  }
  imageLoaded() {
    console.log('loaded');
    // show cropper
//     this.commonSrv.hideSpinner();
  }
  cropperReady() {
    // cropper ready
    console.log('ready');
    this.commonSrv.hideSpinner();
  }
  loadImageFailed() {
    // show message
    console.log('failed');
  }

  close() {
    this.modalCtrl.dismiss();
  }
}

Jag har redan försökt uppdatera changeDetection-strategin, tagit bort några funktionsanrop som jag hade på andra sidor, och de flesta av prestandarekommendationerna, men jag verkar inte hitta orsaken till mitt nuvarande problem

Svar #1

ngx-image-cropper, när du ändrar beskärningsstorlek/position beskärs bilden faktiskt och det är mycket resurskrävande. Om du kan klara dig utan det, kan du bara göra beskärningen en gång genom att sätta autoCrop till false på följande sätt:

<image-cropper
    [imageChangedEvent]="imageChangedEvent"
    [maintainAspectRatio]="true"
    [aspectRatio]="1"
    [autoCrop]="false"
    format="png"
    (imageLoaded)="imageLoaded()"
    (cropperReady)="cropperReady()"
    (loadImageFailed)="loadImageFailed()"
></image-cropper>
<ion-button fill="clear" color="danger" (click)="close()">Cancelar</ion-button>
<ion-button color="green" (click)="save()">Guardar</ion-button>

Använd sedan @ViewChild för att få åtkomst till croppern och därmed beskärningsmetoderna. Här är hur det ser ut i TypeScript-filen:

@ViewChild(ImageCropperComponent) imageCropper: ImageCropperComponent;

Sedan, när användaren väljer att behålla beskärningen, behöver du göra något liknande detta:

function save(): void {
  const event = this.imageCropper.crop();
  this.croppedImage = event.base64;
}

Detta kommer att åtgärda vissa prestandaproblem. Men observera att det verkar som att iDevices har problem med att hantera beskärning på det sätt som ngx-image-cropper gör. Specifikt, om användaren använder kameran medan en bild laddas upp, kan bilden kräva för mycket minne för att konverteras till en base64-sträng i Safari-tråden - som ett resultat kan iDevices frysa vid normal användning. Här är en plats där detta diskuteras: https://github.com/Mawi137/ngx-image-cropper/issues/481