@acorex/components 20.1.37 → 20.1.38
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/acorex-components-image-editor.mjs +70 -58
- package/fesm2022/acorex-components-image-editor.mjs.map +1 -1
- package/fesm2022/{acorex-components-modal-acorex-components-modal-DTUAOsgv.mjs → acorex-components-modal-acorex-components-modal-Bqiz74D1.mjs} +2 -2
- package/fesm2022/{acorex-components-modal-acorex-components-modal-DTUAOsgv.mjs.map → acorex-components-modal-acorex-components-modal-Bqiz74D1.mjs.map} +1 -1
- package/fesm2022/{acorex-components-modal-modal-content.component-Co2yaRpp.mjs → acorex-components-modal-modal-content.component-B-FWjSBZ.mjs} +4 -4
- package/fesm2022/acorex-components-modal-modal-content.component-B-FWjSBZ.mjs.map +1 -0
- package/fesm2022/acorex-components-modal.mjs +1 -1
- package/fesm2022/acorex-components-selection-list-2.mjs +2 -2
- package/fesm2022/acorex-components-selection-list-2.mjs.map +1 -1
- package/image-editor/index.d.ts +6 -10
- package/package.json +12 -12
- package/fesm2022/acorex-components-modal-modal-content.component-Co2yaRpp.mjs.map +0 -1
@@ -6,7 +6,7 @@ import { AXLoadingSpinnerComponent, AXLoadingModule } from '@acorex/components/l
|
|
6
6
|
import * as i2$1 from '@acorex/components/toolbar';
|
7
7
|
import { AXToolBarModule } from '@acorex/components/toolbar';
|
8
8
|
import * as i0 from '@angular/core';
|
9
|
-
import { signal, Injectable, inject, output, ViewEncapsulation, Component, ChangeDetectionStrategy, input, NgZone, ElementRef, viewChild, Renderer2, PLATFORM_ID, effect, afterNextRender,
|
9
|
+
import { signal, Injectable, inject, output, ViewEncapsulation, Component, ChangeDetectionStrategy, input, NgZone, ElementRef, viewChild, Renderer2, PLATFORM_ID, effect, afterNextRender, linkedSignal, contentChild, forwardRef, HostBinding, NgModule } from '@angular/core';
|
10
10
|
import * as i1 from '@angular/forms';
|
11
11
|
import { FormsModule, NG_VALUE_ACCESSOR } from '@angular/forms';
|
12
12
|
import { classes } from 'polytype';
|
@@ -31,8 +31,8 @@ class AXImageEditorService {
|
|
31
31
|
this.penType = signal(null, ...(ngDevMode ? [{ debugName: "penType" }] : []));
|
32
32
|
this.rotate = signal({ state: 0, userInteract: false }, ...(ngDevMode ? [{ debugName: "rotate" }] : []));
|
33
33
|
this.isImageLoad = signal(false, ...(ngDevMode ? [{ debugName: "isImageLoad" }] : []));
|
34
|
-
this.newImage =
|
35
|
-
this.initialImage =
|
34
|
+
this.newImage = null;
|
35
|
+
this.initialImage = null;
|
36
36
|
this.imageBlob = signal([], ...(ngDevMode ? [{ debugName: "imageBlob" }] : []));
|
37
37
|
this.undoPressed = signal(false, ...(ngDevMode ? [{ debugName: "undoPressed" }] : []));
|
38
38
|
this.redoPressed = signal(false, ...(ngDevMode ? [{ debugName: "redoPressed" }] : []));
|
@@ -424,28 +424,43 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.4", ngImpor
|
|
424
424
|
class AXImageEditorViewComponent extends MXBaseComponent {
|
425
425
|
/** @ignore */
|
426
426
|
resizeWindow() {
|
427
|
-
this.canvasResponsive(this.service.newImage
|
427
|
+
this.canvasResponsive(this.service.newImage);
|
428
428
|
}
|
429
429
|
/** @ignore */
|
430
430
|
canvasResponsive(image) {
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
if (
|
436
|
-
this.
|
437
|
-
this.
|
438
|
-
this.canvasElem().nativeElement.width = parentWidth;
|
439
|
-
this.canvasElem().nativeElement.height = parentWidth * this.imageAspect();
|
440
|
-
this.ctx().drawImage(image, 0, 0, parentWidth, parentWidth * this.imageAspect());
|
431
|
+
const imageWidth = image.width;
|
432
|
+
const imageHeight = image.height;
|
433
|
+
this.originalWidth.set(imageWidth);
|
434
|
+
this.originalHeight.set(imageHeight);
|
435
|
+
if (imageWidth > imageHeight) {
|
436
|
+
this.canvasElem().nativeElement.width = imageWidth;
|
437
|
+
this.canvasElem().nativeElement.height = imageWidth;
|
441
438
|
}
|
442
439
|
else {
|
443
|
-
this.
|
444
|
-
this.
|
445
|
-
this.canvasElem().nativeElement.width = imageWidth;
|
446
|
-
this.canvasElem().nativeElement.height = imageWidth / this.imageAspect();
|
447
|
-
this.ctx().drawImage(image, 0, 0, imageWidth, imageWidth / this.imageAspect());
|
440
|
+
this.canvasElem().nativeElement.width = imageHeight;
|
441
|
+
this.canvasElem().nativeElement.height = imageHeight;
|
448
442
|
}
|
443
|
+
this.canvasElem().nativeElement.style.width = '100%';
|
444
|
+
requestAnimationFrame(() => {
|
445
|
+
//recalculate width after canvas size change
|
446
|
+
const recalculateWidth = this.canvasElem().nativeElement.getClientRects()[0]?.width;
|
447
|
+
let scale;
|
448
|
+
if (imageWidth > imageHeight) {
|
449
|
+
scale = this.originalWidth() / recalculateWidth;
|
450
|
+
}
|
451
|
+
else {
|
452
|
+
scale = this.originalHeight() / recalculateWidth;
|
453
|
+
}
|
454
|
+
this.scale.set(scale);
|
455
|
+
this.canvasElem().nativeElement.width = recalculateWidth;
|
456
|
+
this.canvasElem().nativeElement.height = recalculateWidth;
|
457
|
+
if (imageWidth > imageHeight) {
|
458
|
+
this.ctx().drawImage(image, 0, recalculateWidth / 2 - this.originalHeight() / scale / 2, recalculateWidth, this.originalHeight() / scale);
|
459
|
+
}
|
460
|
+
else {
|
461
|
+
this.ctx().drawImage(image, recalculateWidth / 2 - this.originalWidth() / scale / 2, 0, this.originalWidth() / scale, recalculateWidth);
|
462
|
+
}
|
463
|
+
});
|
449
464
|
}
|
450
465
|
/** @ignore */
|
451
466
|
constructor() {
|
@@ -479,29 +494,21 @@ class AXImageEditorViewComponent extends MXBaseComponent {
|
|
479
494
|
/** @ignore */
|
480
495
|
this.renderer = inject(Renderer2);
|
481
496
|
/** @ignore */
|
482
|
-
this.imageAspect = computed(() => {
|
483
|
-
return this.service.initialImage().width / this.service.initialImage().height;
|
484
|
-
}, ...(ngDevMode ? [{ debugName: "imageAspect" }] : []));
|
485
|
-
/** @ignore */
|
486
497
|
this.imageEditorHistory = signal([], ...(ngDevMode ? [{ debugName: "imageEditorHistory" }] : []));
|
487
498
|
/** @ignore */
|
488
499
|
this.imageEditorHistoryPointer = linkedSignal(() => this.imageEditorHistory().length - 1);
|
500
|
+
this.originalWidth = signal(0, ...(ngDevMode ? [{ debugName: "originalWidth" }] : []));
|
501
|
+
this.originalHeight = signal(0, ...(ngDevMode ? [{ debugName: "originalHeight" }] : []));
|
502
|
+
this.scale = signal(0, ...(ngDevMode ? [{ debugName: "scale" }] : []));
|
489
503
|
afterNextRender(() => {
|
490
504
|
this.resizeEventListener = this.renderer.listen(window, 'resize', this.resizeWindow.bind(this));
|
491
|
-
//load image
|
492
|
-
this.service.initialImage.set(new Image());
|
493
|
-
this.service.initialImage().src = this.src();
|
494
|
-
this.service.initialImage().crossOrigin = 'anonymous';
|
495
|
-
this.imageLoadEventListener = this.renderer.listen(this.service.initialImage(), 'load', this.imageLoaded.bind(this));
|
496
505
|
//set canvas options
|
497
506
|
this.ctx.set(this.canvasElem().nativeElement.getContext('2d', { willReadFrequently: true }));
|
498
507
|
this.ctx().lineJoin = 'round';
|
499
508
|
this.ctx().lineCap = 'round';
|
500
509
|
});
|
501
510
|
effect(() => {
|
502
|
-
|
503
|
-
this.canvasResponsive(this.service.initialImage());
|
504
|
-
}
|
511
|
+
this.setInitialImage(this.src());
|
505
512
|
});
|
506
513
|
effect(() => {
|
507
514
|
if (!this.service.undoPressed()) {
|
@@ -528,22 +535,27 @@ class AXImageEditorViewComponent extends MXBaseComponent {
|
|
528
535
|
this.imageLoadEventListener();
|
529
536
|
}
|
530
537
|
}
|
531
|
-
|
532
|
-
|
533
|
-
this.
|
534
|
-
this.service.
|
535
|
-
this.
|
538
|
+
setInitialImage(src) {
|
539
|
+
this.service.initialImage = new Image();
|
540
|
+
this.service.initialImage.src = src;
|
541
|
+
this.service.initialImage.crossOrigin = 'anonymous';
|
542
|
+
this.imageLoadEventListener = this.renderer.listen(this.service.initialImage, 'load', () => {
|
543
|
+
this.imageEditorHistory.set([this.service.initialImage]);
|
544
|
+
this.service.newImage = this.service.initialImage;
|
545
|
+
this.service.isImageLoad.set(true);
|
546
|
+
this.canvasResponsive(this.service.initialImage);
|
547
|
+
});
|
536
548
|
}
|
537
549
|
/** @ignore */
|
538
550
|
imageChanged() {
|
539
551
|
if (this.service.undoPressed() && this.imageEditorHistoryPointer() >= 1) {
|
540
552
|
this.imageEditorHistoryPointer.update((prev) => prev - 1);
|
541
|
-
this.service.newImage
|
553
|
+
this.service.newImage = this.imageEditorHistory()[this.imageEditorHistoryPointer()];
|
542
554
|
this.canvasResponsive(this.imageEditorHistory()[this.imageEditorHistoryPointer()]);
|
543
555
|
}
|
544
556
|
if (this.service.redoPressed() && this.imageEditorHistoryPointer() < this.imageEditorHistory().length - 1) {
|
545
557
|
this.imageEditorHistoryPointer.update((prev) => prev + 1);
|
546
|
-
this.service.newImage
|
558
|
+
this.service.newImage = this.imageEditorHistory()[this.imageEditorHistoryPointer()];
|
547
559
|
this.canvasResponsive(this.imageEditorHistory()[this.imageEditorHistoryPointer()]);
|
548
560
|
}
|
549
561
|
this.service.undoPressed.set(false);
|
@@ -565,10 +577,6 @@ class AXImageEditorViewComponent extends MXBaseComponent {
|
|
565
577
|
}
|
566
578
|
}
|
567
579
|
/** @ignore */
|
568
|
-
getBoundingCanvasHandler() {
|
569
|
-
return this.canvasElem().nativeElement.getBoundingClientRect();
|
570
|
-
}
|
571
|
-
/** @ignore */
|
572
580
|
mouseDownHandler(e) {
|
573
581
|
this.isMouseDown.set(true);
|
574
582
|
if (!this.service.penType())
|
@@ -604,7 +612,8 @@ class AXImageEditorViewComponent extends MXBaseComponent {
|
|
604
612
|
this.canvasElem().nativeElement.width = cropRect.width;
|
605
613
|
this.canvasElem().nativeElement.height = cropRect.height;
|
606
614
|
this.ctx().putImageData(imageData, 0, 0);
|
607
|
-
this.
|
615
|
+
const cropImage = this.canvasElem().nativeElement.toDataURL('image/jpeg', 1);
|
616
|
+
this.setInitialImage(cropImage);
|
608
617
|
this.service.activeToolState.set(null);
|
609
618
|
}
|
610
619
|
/** @ignore */
|
@@ -612,9 +621,19 @@ class AXImageEditorViewComponent extends MXBaseComponent {
|
|
612
621
|
this.ctx().globalAlpha = 1;
|
613
622
|
this.ctx().save();
|
614
623
|
this.ctx().clearRect(0, 0, this.canvasElem().nativeElement.width, this.canvasElem().nativeElement.height);
|
615
|
-
|
616
|
-
|
617
|
-
|
624
|
+
// Calculate scale factor to fit rotated image within canvas
|
625
|
+
const rotationAngle = (this.service.rotate().state * Math.PI) / 180;
|
626
|
+
const cos = Math.abs(Math.cos(rotationAngle));
|
627
|
+
const sin = Math.abs(Math.sin(rotationAngle));
|
628
|
+
const rotatedWidth = this.service.newImage.width * cos + this.service.newImage.height * sin;
|
629
|
+
const rotatedHeight = this.service.newImage.width * sin + this.service.newImage.height * cos;
|
630
|
+
const scaleX = this.canvasElem().nativeElement.width / rotatedWidth;
|
631
|
+
const scaleY = this.canvasElem().nativeElement.height / rotatedHeight;
|
632
|
+
const scale = Math.min(scaleX, scaleY);
|
633
|
+
this.ctx().translate(this.canvasElem().nativeElement.width / 2, this.canvasElem().nativeElement.height / 2);
|
634
|
+
this.ctx().rotate(rotationAngle);
|
635
|
+
this.ctx().scale(scale, scale);
|
636
|
+
this.ctx().drawImage(this.service.newImage, -this.service.newImage.width / 2, -this.service.newImage.height / 2);
|
618
637
|
this.ctx().restore();
|
619
638
|
this.saveImageChange();
|
620
639
|
this.service.rotate.update((prev) => {
|
@@ -626,7 +645,7 @@ class AXImageEditorViewComponent extends MXBaseComponent {
|
|
626
645
|
const newImage = new Image();
|
627
646
|
newImage.crossOrigin = 'anonymous';
|
628
647
|
newImage.src = this.canvasElem().nativeElement.toDataURL('image/jpeg', 1);
|
629
|
-
this.service.newImage
|
648
|
+
this.service.newImage = newImage;
|
630
649
|
this.imageEditorHistory.update((prev) => [...prev, newImage]);
|
631
650
|
const tempBlob = [];
|
632
651
|
this.canvasElem().nativeElement.toBlob((blob) => {
|
@@ -640,20 +659,13 @@ class AXImageEditorViewComponent extends MXBaseComponent {
|
|
640
659
|
}, 'image/webp', 1);
|
641
660
|
this.service.imageBlob.set(tempBlob);
|
642
661
|
}
|
643
|
-
/** @ignore */
|
644
|
-
get __hostStyle() {
|
645
|
-
return `width: ${this.service.initialImage()?.width}px; height: ${this.service.initialImage()?.height}px`;
|
646
|
-
}
|
647
662
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: AXImageEditorViewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
648
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.2.4", type: AXImageEditorViewComponent, isStandalone: true, selector: "ax-image-editor-view", inputs: { showGrid: { classPropertyName: "showGrid", publicName: "showGrid", isSignal: true, isRequired: false, transformFunction: null }, src: { classPropertyName: "src", publicName: "src", isSignal: true, isRequired: false, transformFunction: null } },
|
663
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.2.4", type: AXImageEditorViewComponent, isStandalone: true, selector: "ax-image-editor-view", inputs: { showGrid: { classPropertyName: "showGrid", publicName: "showGrid", isSignal: true, isRequired: false, transformFunction: null }, src: { classPropertyName: "src", publicName: "src", isSignal: true, isRequired: false, transformFunction: null } }, providers: [{ provide: AXComponent, useExisting: AXImageEditorViewComponent }], viewQueries: [{ propertyName: "canvasElem", first: true, predicate: ["canvasElem"], descendants: true, isSignal: true }, { propertyName: "cropperWindow", first: true, predicate: ["f"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<canvas\n tabindex=\"1\"\n (pointerdown)=\"mouseDownHandler($event)\"\n (pointerup)=\"mouseUpHandler()\"\n (pointermove)=\"mouseMoveHandler($event)\"\n class=\"ax-canvas-element\"\n #canvasElem\n></canvas>\n\n@if (this.service.activeToolState() === 'crop') {\n <ax-image-editor-cropper-window [showGrid]=\"showGrid()\" #f></ax-image-editor-cropper-window>\n}\n", styles: ["ax-image-editor-view{position:relative;display:flex;justify-content:center;align-items:center;background-color:#fff;width:100%;touch-action:none;overflow:hidden}ax-image-editor-view .ax-canvas-element{cursor:crosshair;background-color:#000}ax-image-editor-view .ax-crop-save{position:absolute;top:0;right:0;margin:1rem}\n"], dependencies: [{ kind: "component", type: AXImageEditorCropperWindowComponent, selector: "ax-image-editor-cropper-window", inputs: ["showGrid"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
649
664
|
}
|
650
665
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.4", ngImport: i0, type: AXImageEditorViewComponent, decorators: [{
|
651
666
|
type: Component,
|
652
|
-
args: [{ selector: 'ax-image-editor-view', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [AXImageEditorCropperWindowComponent], providers: [{ provide: AXComponent, useExisting: AXImageEditorViewComponent }], template: "<canvas\n tabindex=\"1\"\n (pointerdown)=\"mouseDownHandler($event)\"\n (pointerup)=\"mouseUpHandler()\"\n (pointermove)=\"mouseMoveHandler($event)\"\n class=\"ax-canvas-element\"\n #canvasElem\n></canvas>\n\n@if (this.service.activeToolState() === 'crop') {\n <ax-image-editor-cropper-window [showGrid]=\"showGrid()\" #f></ax-image-editor-cropper-window>\n}\n", styles: ["ax-image-editor-view{position:relative;display:flex;justify-content:center;align-items:center;background-color:#fff;width:100%;touch-action:none;overflow:hidden}ax-image-editor-view .ax-canvas-element{cursor:crosshair}ax-image-editor-view .ax-crop-save{position:absolute;top:0;right:0;margin:1rem}\n"] }]
|
653
|
-
}], ctorParameters: () => []
|
654
|
-
type: HostBinding,
|
655
|
-
args: ['style']
|
656
|
-
}] } });
|
667
|
+
args: [{ selector: 'ax-image-editor-view', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [AXImageEditorCropperWindowComponent], providers: [{ provide: AXComponent, useExisting: AXImageEditorViewComponent }], template: "<canvas\n tabindex=\"1\"\n (pointerdown)=\"mouseDownHandler($event)\"\n (pointerup)=\"mouseUpHandler()\"\n (pointermove)=\"mouseMoveHandler($event)\"\n class=\"ax-canvas-element\"\n #canvasElem\n></canvas>\n\n@if (this.service.activeToolState() === 'crop') {\n <ax-image-editor-cropper-window [showGrid]=\"showGrid()\" #f></ax-image-editor-cropper-window>\n}\n", styles: ["ax-image-editor-view{position:relative;display:flex;justify-content:center;align-items:center;background-color:#fff;width:100%;touch-action:none;overflow:hidden}ax-image-editor-view .ax-canvas-element{cursor:crosshair;background-color:#000}ax-image-editor-view .ax-crop-save{position:absolute;top:0;right:0;margin:1rem}\n"] }]
|
668
|
+
}], ctorParameters: () => [] });
|
657
669
|
|
658
670
|
/**
|
659
671
|
* paint container.
|
@@ -674,7 +686,7 @@ class AXImageEditorContainerComponent extends classes((MXInputBaseValueComponent
|
|
674
686
|
* @returns void - No return value. The edited image is saved and the onValueChanged event is emitted.
|
675
687
|
*/
|
676
688
|
save() {
|
677
|
-
if (this.service.initialImage
|
689
|
+
if (this.service.initialImage !== this.service.newImage) {
|
678
690
|
this.commitValue(this.service.imageBlob(), true);
|
679
691
|
}
|
680
692
|
else {
|