Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/albas improvements #644

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 14 additions & 40 deletions projects/demo-app/src/app/app.component.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<input [(ngModel)]="imageURL" placeholder="URL to load image" type="text" />
<input id="imageURL" placeholder="URL to load image" type="text" (keyup)="debounce($event)" />
<input type="file" (change)="fileChangeEvent($event)" accept="image/*" />
<br />
<br />
Expand All @@ -18,68 +18,42 @@
<input id="cropperMaxHeight" type="number" (keyup)="debounce($event)"/>
</section>
<br />
<button (click)="maintainAspectRatio = !maintainAspectRatio;" [class.enabled]="maintainAspectRatio">Maintain Aspect Ratio</button>
<button (click)="toggleAspectRatio()" [class.enabled]="maintainAspectRatio || containWithinAspectRatio">Aspect ratio: {{aspectRatio === 4/3 ? '4/3' : '16/5'}}</button>
<button (click)="containWithinAspectRatio = !containWithinAspectRatio;" [class.enabled]="containWithinAspectRatio">Fill Aspect Ratio</button>
<button (click)="settingsToUpdate = { maintainAspectRatio: !settings.maintainAspectRatio }" [class.enabled]="settings.maintainAspectRatio">Maintain Aspect Ratio</button>
<button (click)="toggleAspectRatio()" [class.enabled]="settings.maintainAspectRatio || settings.containWithinAspectRatio">Aspect ratio: {{settings.aspectRatio === 4/3 ? '4/3' : '16/5'}}</button>
<button (click)="settingsToUpdate = { containWithinAspectRatio: !settings.containWithinAspectRatio }" [class.enabled]="settings.containWithinAspectRatio">Fill Aspect Ratio</button>
<button (click)="rotateLeft()">Rotate left</button>
<button (click)="rotateRight()">Rotate right</button>
<br />
<br />
<input [ngModel]="transform.rotate!" placeholder="Rotation" type="number" (ngModelChange)="updateRotation($event)" />
<input [ngModel]="settings.transform.rotate" placeholder="Rotation" type="number" (ngModelChange)="updateRotation($event)" />
<button (click)="zoomOut()">Zoom -</button>
<button (click)="zoomIn()">Zoom +</button>
<button (click)="moveLeft()">move left</button>
<button (click)="moveRight()">move right</button>
<button (click)="moveUp()">move up</button>
<button (click)="moveDown()">move down</button>
<button (click)="flipHorizontal()" [class.enabled]="transform.flipH">Flip horizontal</button>
<button (click)="flipVertical()" [class.enabled]="transform.flipV">Flip vertical</button>
<button (click)="allowMoveImage = !allowMoveImage;" [class.enabled]="allowMoveImage">Image panning</button>
<button (click)="flipHorizontal()" [class.enabled]="settings.transform.flipX">Flip horizontal</button>
<button (click)="flipVertical()" [class.enabled]="settings.transform.flipY">Flip vertical</button>
<button (click)="settingsToUpdate = { allowMoveImage: !settings.allowMoveImage}" [class.enabled]="settings.allowMoveImage">Image panning</button>
<br/>
<br/>
<button (click)="hidden = !hidden;" [class.hidden]="maintainAspectRatio">Hidden</button>
<button (click)="disabled = !disabled;" [class.enabled]="disabled">Disable</button>
<button (click)="hideResizeSquares = !hideResizeSquares;" [class.enabled]="hideResizeSquares">Hide Resize Squares</button>
<button (click)="resetCropOnAspectRatioChange = !resetCropOnAspectRatioChange;" [class.enabled]="resetCropOnAspectRatioChange">Reset Crop On Aspect Ratio Change</button>
<button (click)="toggleBackgroundColor()" style="color:white" [style.background-color]="backgroundColor">Background Color</button>
<button (click)="settingsToUpdate = { hidden: !settings.hidden }" [class.hidden]="settings.maintainAspectRatio">Hidden</button>
<button (click)="settingsToUpdate = { disabled: !settings.disabled }" [class.enabled]="settings.disabled">Disable</button>
<button (click)="settingsToUpdate = { hideResizeSquares: !settings.hideResizeSquares }" [class.enabled]="settings.hideResizeSquares">Hide Resize Squares</button>
<button (click)="toggleBackgroundColor()" [style.color]="settings.backgroundColor ? 'white': '#007bff'" [style.background-color]="settings.backgroundColor">Background Color</button>
<button (click)="test()">Random test</button>
<button (click)="resetImage()">Reset image</button>
<br/>
<br/>

<div [style.display]="showCropper ? null : 'none'" class="cropper-wrapper">
<image-cropper
[imageChangedEvent]="imageChangedEvent"
[imageURL]="imageURL"
[hidden]="hidden"
[disabled]="disabled"
[alignImage]="alignImage"
[roundCropper]="roundCropper"
[backgroundColor]="backgroundColor"
imageAltText="Alternative image text"
[allowMoveImage]="allowMoveImage"
[hideResizeSquares]="hideResizeSquares"
[canvasRotation]="canvasRotation"
[aspectRatio]="aspectRatio"
[containWithinAspectRatio]="containWithinAspectRatio"
[maintainAspectRatio]="maintainAspectRatio"
[cropperStaticWidth]="cropperStaticWidth"
[cropperStaticHeight]="cropperStaticHeight"
[cropperMinWidth]="cropperMinWidth"
[cropperMinHeight]="cropperMinHeight"
[cropperMaxWidth]="cropperMaxWidth"
[cropperMaxHeight]="cropperMaxHeight"
[resetCropOnAspectRatioChange]="resetCropOnAspectRatioChange"
[(cropper)]="cropper"
[(transform)]="transform"
[onlyScaleDown]="true"
output="blob"
format="png"
[settingsToUpdate]="settingsToUpdate"
(settingsUpdated)="settingsUpdated($event)"
(imageCropped)="imageCropped($event)"
loiddy marked this conversation as resolved.
Show resolved Hide resolved
(imageLoaded)="imageLoaded()"
(cropperReady)="cropperReady($event)"
(loadImageFailed)="loadImageFailed()"
(transformChange)="transformChange($event)"
></image-cropper>
<div *ngIf="loading" class="loader">Loading...</div>
</div>
Expand Down
172 changes: 56 additions & 116 deletions projects/demo-app/src/app/app.component.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import { Component } from '@angular/core';
import {
CropperPosition,
Dimensions,
getCropperInitValue,
getTransformInitValue,
getImageCropperSettingsInitValue,
ImageCroppedEvent,
ImageCropperComponent,
ImageTransform
ImageCropperSettings,
PartialImageCropperSettings,
} from 'ngx-image-cropper';
import { DomSanitizer, SafeUrl } from '@angular/platform-browser';
import { NgIf } from '@angular/common';
Expand All @@ -22,39 +25,11 @@ export class AppComponent {
loading = false;
croppedImage: SafeUrl = '';

imageChangedEvent: Event | null = null;
imageURL?: string;
hidden = false;
disabled = false;
alignImage = 'center' as const;
roundCropper = false;
backgroundColor = 'red';
allowMoveImage = false;
hideResizeSquares = false;
canvasRotation = 0;
aspectRatio = 4 / 3;
containWithinAspectRatio = false;
maintainAspectRatio = false;
cropperStaticWidth = 0;
cropperStaticHeight = 0;
cropperMinWidth = 0;
cropperMinHeight = 0;
cropperMaxWidth = 0;
cropperMaxHeight = 0;
resetCropOnAspectRatioChange = true;
cropper?: CropperPosition;
transform: ImageTransform = {
translateUnit: 'px',
scale: 1,
rotate: 0,
flipH: false,
flipV: false,
translateH: 0,
translateV: 0
};

timeout: any;
eventList = {};

settings: ImageCropperSettings = getImageCropperSettingsInitValue();
settingsToUpdate: PartialImageCropperSettings = { aspectRatio: 16/5 };

constructor(
private sanitizer: DomSanitizer
Expand All @@ -63,153 +38,121 @@ export class AppComponent {

fileChangeEvent(event: Event): void {
this.loading = true;
this.imageChangedEvent = event;
}

imageCropped(event: ImageCroppedEvent) {
this.croppedImage = this.sanitizer.bypassSecurityTrustUrl(event.objectUrl || event.base64 || '');
console.log('CROPPED', event);
this.settingsToUpdate = { imageSource: { imageChangedEvent : event } }
}

imageLoaded() {
this.showCropper = true;
console.log('Image loaded');
}

loadImageFailed() {
console.error('Load image failed');
}

settingsUpdated(settings: ImageCropperSettings){
this.settings = settings;
}

cropperReady(sourceImageDimensions: Dimensions) {
console.log('Cropper ready', sourceImageDimensions);
this.loading = false;
}

loadImageFailed() {
console.error('Load image failed');
}

transformChange(transform: ImageTransform) {
console.log('transform changed', transform);
imageCropped(event: ImageCroppedEvent) {
this.croppedImage = this.sanitizer.bypassSecurityTrustUrl(event.objectUrl || event.base64 || '');
console.log('CROPPED', event);
loiddy marked this conversation as resolved.
Show resolved Hide resolved
}

rotateLeft() {
this.loading = true;
setTimeout(() => { // Use timeout because rotating image is a heavy operation and will block the ui thread
this.canvasRotation--;
this.flipAfterRotate();
this.settingsToUpdate = { canvasRotation: --this.settings.canvasRotation, ...this.flipAfterRotate() };
loiddy marked this conversation as resolved.
Show resolved Hide resolved
});
}

rotateRight() {
this.loading = true;
setTimeout(() => {
this.canvasRotation++;
this.flipAfterRotate();
setTimeout(() => {
this.settingsToUpdate = { canvasRotation: ++this.settings.canvasRotation, ...this.flipAfterRotate() };
});
}

moveLeft() {
this.transform = {
...this.transform,
translateH: this.transform.translateH! - 1
};
this.settingsToUpdate = { transform: { translateX: --this.settings.transform.translateX } };
}

moveRight() {
this.transform = {
...this.transform,
translateH: this.transform.translateH! + 1
};
this.settingsToUpdate = { transform: { translateX: this.settings.transform.translateX + 1 } };
}

moveDown() {
this.transform = {
...this.transform,
translateV: this.transform.translateV! + 1
};
moveUp() {
this.settingsToUpdate = { transform: { translateY: --this.settings.transform.translateY } };
}

moveUp() {
this.transform = {
...this.transform,
translateV: this.transform.translateV! - 1
};
moveDown() {
this.settingsToUpdate = { transform: { translateY: ++this.settings.transform.translateY } };
}

private flipAfterRotate() {
const flippedH = this.transform.flipH;
const flippedV = this.transform.flipV;
this.transform = {
...this.transform,
flipH: flippedV,
flipV: flippedH,
translateH: 0,
translateV: 0
return {
transform: {
flipX: this.settings.transform.flipY,
flipY: this.settings.transform.flipX,
translateX: 0,
translateY: 0
}
};
}

flipHorizontal() {
this.transform = {
...this.transform,
flipH: !this.transform.flipH
};
this.settingsToUpdate = { transform: { flipX: !this.settings.transform.flipX } };
}

flipVertical() {
this.transform = {
...this.transform,
flipV: !this.transform.flipV
};
this.settingsToUpdate = { transform: { flipY: !this.settings.transform.flipY } };
}

resetImage() {
this.canvasRotation = 0;
this.cropper = undefined;
this.maintainAspectRatio = false;
this.transform = {
translateUnit: 'px',
scale: 1,
rotate: 0,
flipH: false,
flipV: false,
translateH: 0,
translateV: 0
this.settingsToUpdate = {
canvasRotation: 0,
cropper: getCropperInitValue(),
maintainAspectRatio: false,
transform: getTransformInitValue(),
};
}

zoomOut() {
this.transform = {
...this.transform,
scale: this.transform.scale! - .1
};
this.settingsToUpdate = { transform: { scale: this.settings.transform.scale - .1 } };
}

zoomIn() {
this.transform = {
...this.transform,
scale: this.transform.scale! + .1
};
this.settingsToUpdate = { transform: { scale: this.settings.transform.scale + .1 } };
}

updateRotation(rotate: number) {
this.transform = {
...this.transform,
rotate
};
this.settingsToUpdate = { transform: { scale: this.settings.transform.rotate } };
}

toggleAspectRatio() {
this.aspectRatio = this.aspectRatio === 4 / 3 ? 16 / 5 : 4 / 3;
this.settingsToUpdate = { aspectRatio: this.settings.aspectRatio === 4 / 3 ? 16 / 5 : 4 / 3 };
}

toggleBackgroundColor() {
this.backgroundColor = this.backgroundColor === 'red' ? 'blue' : 'red';
this.settingsToUpdate = { backgroundColor: this.settings.backgroundColor === 'red' ? 'blue' : 'red' };
}

// prevent over triggering app when typing
debounce(event: any) {
clearTimeout(this.timeout);
(this.eventList as any)[event.target!.id] = event.target.value;
(this.eventList as any)[event.target.id] = event.target.value;
this.timeout = setTimeout(() => {
for (const [key, value] of Object.entries(this.eventList)) {
(this as any)[key] = Number(value);
if (key === 'imageURL') {
this.settingsToUpdate = { imageSource: { [key]: value as string }};
} else {
this.settingsToUpdate = { [key]: Number(value) };
}
}
this.eventList = {};
}, 500);
Expand All @@ -220,11 +163,8 @@ export class AppComponent {
use it to test whatever you want
*/
test() {
this.canvasRotation = 3;
this.transform = {
...this.transform,
scale: 2
this.settingsToUpdate = {
cropper: { x1: 50, y1: 50, x2: 250, y2: 112.5 } // has 16/5 aspect ratio
};
this.cropper = {x1: 190, y1: 221.5, x2: 583, y2: 344.3125}; // has 16/5 aspect ratio
}
}
Loading
Loading