Closed SoulDee closed 9 months ago
How the app works now, I reckon you can...
If you want to see the cropper load the next img showing the state of the previous img, keep the cropper visibly hidden till you get the cropperReady event, pass in the previous cropper and transform and then change it back to visible.
I haven't tried this. But looking at how the app is now it should work. Happy to look at it if it doesn't work and you set up an example. Best of luck :)
How the app works now, I reckon you can...
- Deep clone the transform and cropper (cropper position) inputs after you have cropped your first img in the array. If there's problems with your cropper input not being updated to the latest values, cropping triggers the ImageCroppedEvent that sends an object with data including the cropperPosition. Make sure to deep clone these variables so the property values aren't updated later on. They are objects. {...obj} works.
- Load the next img in the array.
- Wait till the cropper is ready.
- Send in the copied transform and cropper inputs. If mantainAspect ratio was true before, make it false. Having it as true triggers a "new" cropper, overriding the cropper you send in.
- Crop or use auto crop and repeat with the next img.
If you want to see the cropper load the next img showing the state of the previous img, keep the cropper visibly hidden till you get the cropperReady event, pass in the previous cropper and transform and then change it back to visible.
I haven't tried this. But looking at how the app is now it should work. Happy to look at it if it doesn't work and you set up an example. Best of luck :)
Thank you for your help. Now my app is working, but there's a small issue. The new cropper doesn't work in cropperReady, but the transform works. After adding a setTimeout, the new cropper works well. I have provided code in the reply below.
Anyway, it does work now! (^◡^)
import {Component, ViewChild} from '@angular/core';
import {DomSanitizer} from '@angular/platform-browser';
import {CropperPosition, ImageCropperComponent, ImageTransform} from 'ngx-image-cropper';
@Component({
selector: 'app-root',
template: `
<button (click)="loadImage()">Load Image</button>
<button (click)="zoomIn()">Zoom In</button>
<button (click)="zoomOut()">Zoom Out</button>
<button (click)="crop()">Run Crop Gif</button>
<div class="cropper-wrapper">
<image-cropper
#imageCropperRef
[imageURL]="imageUrl"
[autoCrop]="false"
[maintainAspectRatio]="false"
[(transform)]="transform"
[cropper]="cropper"
(cropperReady)="cropperReady()"
></image-cropper>
</div>
<ng-container *ngIf="!loading">
<div *ngFor="let frame of croppedImages">
<img [src]="frame" />
</div>
</ng-container>
`,
styles: [
`
image-cropper {
max-height: 50vh;
}
.cropper-wrapper {
min-height: 300px;
position: relative;
}
`,
],
})
export class AppComponent {
@ViewChild('imageCropperRef') imageCropperRef?: ImageCropperComponent;
croppedImages: any[] = [];
imageUrl?: string;
imageUrls = ['assets/cat_1.jpg', 'assets/cat_2.jpg', 'assets/cat_3.jpg'];
loadCursor = 0;
scale = 1;
transform: ImageTransform = {
translateUnit: 'px',
};
cropper: CropperPosition = {
x1: 0,
y1: 0,
x2: 160,
y2: 160,
};
loading = false;
cacheTransform: ImageTransform = {
translateUnit: 'px',
};
cacheCropper: CropperPosition = {
x1: 0,
y1: 0,
x2: 160,
y2: 160,
};
constructor(private sanitizer: DomSanitizer) {}
loadImage() {
if (this.loadCursor < this.imageUrls.length) {
this.imageUrl = this.imageUrls[this.loadCursor];
}
}
addCropped() {
const event = this.imageCropperRef?.crop('base64'); // Using Blob will return a Promise.
if (event) {
const url = this.sanitizer.bypassSecurityTrustUrl(event.objectUrl || event.base64 || '');
this.croppedImages.push(url);
}
}
cropperReady() {
if (this.loading) {
this.transform = {...this.cacheTransform};
this.cropper = {...this.cacheCropper};
setTimeout(() => {
// If there is no setTimeout, the changes to the cropper will not take effect.
this.addCropped();
this.loadNextImage();
}, 0);
}
}
loadNextImage() {
this.loadCursor++;
if (this.loadCursor >= this.imageUrls.length) {
this.loadCursor = 0;
this.loading = false;
}
this.loadImage();
}
zoomOut() {
this.scale -= 0.1;
this.transform = {
...this.transform,
scale: this.scale,
};
}
zoomIn() {
this.scale += 0.1;
this.transform = {
...this.transform,
scale: this.scale,
};
}
crop() {
this.loading = true;
this.croppedImages = [];
this.cacheTransform = {...this.transform};
this.cacheCropper = {...this.cropper};
this.addCropped();
this.loadNextImage();
}
}
not sure why that's happening but happy you found a solution for it
I'm trying to crop a GIF image, but the output format is PNG. After some consideration, I came up with a method, which is to obtain a PNG image array from the GIF image through another process. Then, apply the cropping process of ngx-image-cropper to each image to obtain a cropped array.
At first, my idea was to obtain an array of images, then replace the images. However, when I tried opening another image, the component's state was reset. The source code confirmed my suspicion, so this approach cannot be used to crop an array of images.