@bensitu/image-editor 1.3.0 → 1.3.1
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/dist/image-editor.esm.js +230 -277
- package/dist/image-editor.esm.js.map +2 -2
- package/dist/image-editor.esm.min.js +3 -3
- package/dist/image-editor.esm.min.js.map +3 -3
- package/dist/image-editor.esm.min.mjs +3 -3
- package/dist/image-editor.esm.min.mjs.map +3 -3
- package/dist/image-editor.esm.mjs +230 -277
- package/dist/image-editor.esm.mjs.map +2 -2
- package/dist/image-editor.js +230 -277
- package/dist/image-editor.js.map +2 -2
- package/dist/image-editor.min.js +2 -2
- package/dist/image-editor.min.js.map +3 -3
- package/package.json +9 -4
- package/src/image-editor.js +104 -54
package/dist/image-editor.esm.js
CHANGED
|
@@ -5,19 +5,16 @@ import fabricModule from "fabric";
|
|
|
5
5
|
/**
|
|
6
6
|
* @file image-editor.js
|
|
7
7
|
* @module image-editor
|
|
8
|
-
* @version 1.3.
|
|
8
|
+
* @version 1.3.1
|
|
9
9
|
* @author Ben Situ
|
|
10
10
|
* @license MIT
|
|
11
11
|
* @description Lightweight canvas-based image editor with masking/transform/export support.
|
|
12
12
|
*/
|
|
13
13
|
var fabric = null;
|
|
14
14
|
function getGlobalScope() {
|
|
15
|
-
if (typeof globalThis !== "undefined")
|
|
16
|
-
|
|
17
|
-
if (typeof
|
|
18
|
-
return self;
|
|
19
|
-
if (typeof window !== "undefined")
|
|
20
|
-
return window;
|
|
15
|
+
if (typeof globalThis !== "undefined") return globalThis;
|
|
16
|
+
if (typeof self !== "undefined") return self;
|
|
17
|
+
if (typeof window !== "undefined") return window;
|
|
21
18
|
return null;
|
|
22
19
|
}
|
|
23
20
|
function getGlobalFabric() {
|
|
@@ -29,8 +26,7 @@ function setFabric(fabricInstance2) {
|
|
|
29
26
|
return fabric;
|
|
30
27
|
}
|
|
31
28
|
function ensureFabric() {
|
|
32
|
-
if (!fabric)
|
|
33
|
-
setFabric();
|
|
29
|
+
if (!fabric) setFabric();
|
|
34
30
|
return fabric;
|
|
35
31
|
}
|
|
36
32
|
var ImageEditor = class {
|
|
@@ -198,8 +194,7 @@ var ImageEditor = class {
|
|
|
198
194
|
* });
|
|
199
195
|
*/
|
|
200
196
|
init(idMap = {}) {
|
|
201
|
-
if (!this._fabricLoaded)
|
|
202
|
-
return;
|
|
197
|
+
if (!this._fabricLoaded) return;
|
|
203
198
|
const defaults = {
|
|
204
199
|
canvas: "fabricCanvas",
|
|
205
200
|
canvasContainer: null,
|
|
@@ -240,8 +235,7 @@ var ImageEditor = class {
|
|
|
240
235
|
}
|
|
241
236
|
_reportError(message, error = null) {
|
|
242
237
|
const handler = this.options && this.options.onError;
|
|
243
|
-
if (typeof handler !== "function")
|
|
244
|
-
return;
|
|
238
|
+
if (typeof handler !== "function") return;
|
|
245
239
|
try {
|
|
246
240
|
handler(error, message);
|
|
247
241
|
} catch {
|
|
@@ -249,8 +243,7 @@ var ImageEditor = class {
|
|
|
249
243
|
}
|
|
250
244
|
_reportWarning(message, error = null) {
|
|
251
245
|
const handler = this.options && this.options.onWarning;
|
|
252
|
-
if (typeof handler !== "function")
|
|
253
|
-
return;
|
|
246
|
+
if (typeof handler !== "function") return;
|
|
254
247
|
try {
|
|
255
248
|
handler(error, message);
|
|
256
249
|
} catch {
|
|
@@ -264,8 +257,7 @@ var ImageEditor = class {
|
|
|
264
257
|
*/
|
|
265
258
|
_initCanvas() {
|
|
266
259
|
const canvasElement = document.getElementById(this.elements.canvas);
|
|
267
|
-
if (!canvasElement)
|
|
268
|
-
throw new Error("Canvas is not found: " + this.elements.canvas);
|
|
260
|
+
if (!canvasElement) throw new Error("Canvas is not found: " + this.elements.canvas);
|
|
269
261
|
this.canvasElement = canvasElement;
|
|
270
262
|
if (this.elements.canvasContainer) {
|
|
271
263
|
const containerElement = document.getElementById(this.elements.canvasContainer);
|
|
@@ -295,16 +287,13 @@ var ImageEditor = class {
|
|
|
295
287
|
this.canvas.on("selection:updated", (event) => this._handleSelectionChanged(event.selected));
|
|
296
288
|
this.canvas.on("selection:cleared", () => this._handleSelectionChanged([]));
|
|
297
289
|
this.canvas.on("object:moving", (event) => {
|
|
298
|
-
if (event.target && event.target.maskId)
|
|
299
|
-
this._syncMaskLabel(event.target);
|
|
290
|
+
if (event.target && event.target.maskId) this._syncMaskLabel(event.target);
|
|
300
291
|
});
|
|
301
292
|
this.canvas.on("object:scaling", (event) => {
|
|
302
|
-
if (event.target && event.target.maskId)
|
|
303
|
-
this._syncMaskLabel(event.target);
|
|
293
|
+
if (event.target && event.target.maskId) this._syncMaskLabel(event.target);
|
|
304
294
|
});
|
|
305
295
|
this.canvas.on("object:rotating", (event) => {
|
|
306
|
-
if (event.target && event.target.maskId)
|
|
307
|
-
this._syncMaskLabel(event.target);
|
|
296
|
+
if (event.target && event.target.maskId) this._syncMaskLabel(event.target);
|
|
308
297
|
});
|
|
309
298
|
this.canvas.on("object:modified", (event) => this._handleObjectModified(event.target));
|
|
310
299
|
this.canvasElement.style.display = "block";
|
|
@@ -318,11 +307,9 @@ var ImageEditor = class {
|
|
|
318
307
|
*/
|
|
319
308
|
_handleObjectModified(target) {
|
|
320
309
|
const masks = this._getModifiedMasks(target);
|
|
321
|
-
if (!masks.length)
|
|
322
|
-
return;
|
|
310
|
+
if (!masks.length) return;
|
|
323
311
|
masks.forEach((mask) => {
|
|
324
|
-
if (typeof mask.setCoords === "function")
|
|
325
|
-
mask.setCoords();
|
|
312
|
+
if (typeof mask.setCoords === "function") mask.setCoords();
|
|
326
313
|
this._syncMaskLabel(mask);
|
|
327
314
|
});
|
|
328
315
|
this._expandCanvasToFitObjects(masks);
|
|
@@ -336,10 +323,8 @@ var ImageEditor = class {
|
|
|
336
323
|
* @private
|
|
337
324
|
*/
|
|
338
325
|
_getModifiedMasks(target) {
|
|
339
|
-
if (!target)
|
|
340
|
-
|
|
341
|
-
if (target.maskId)
|
|
342
|
-
return [target];
|
|
326
|
+
if (!target) return [];
|
|
327
|
+
if (target.maskId) return [target];
|
|
343
328
|
const objects = typeof target.getObjects === "function" ? target.getObjects() : [];
|
|
344
329
|
return Array.isArray(objects) ? objects.filter((object) => object && object.maskId) : [];
|
|
345
330
|
}
|
|
@@ -352,8 +337,7 @@ var ImageEditor = class {
|
|
|
352
337
|
* @private
|
|
353
338
|
*/
|
|
354
339
|
_syncContainerOverflow(options = {}) {
|
|
355
|
-
if (!this.containerElement || !this.containerElement.style)
|
|
356
|
-
return;
|
|
340
|
+
if (!this.containerElement || !this.containerElement.style) return;
|
|
357
341
|
if (this._containerOriginalOverflow === void 0) {
|
|
358
342
|
this._containerOriginalOverflow = this.containerElement.style.overflow || "";
|
|
359
343
|
}
|
|
@@ -381,14 +365,12 @@ var ImageEditor = class {
|
|
|
381
365
|
_bindEvents() {
|
|
382
366
|
this._bindIfExists("uploadArea", "click", () => {
|
|
383
367
|
const uploadAreaElement = document.getElementById(this.elements.uploadArea);
|
|
384
|
-
if (this._isElementDisabled(uploadAreaElement))
|
|
385
|
-
return;
|
|
368
|
+
if (this._isElementDisabled(uploadAreaElement)) return;
|
|
386
369
|
document.getElementById(this.elements.imageInput)?.click();
|
|
387
370
|
});
|
|
388
371
|
this._bindIfExists("imageInput", "change", (event) => {
|
|
389
372
|
const file = event.target.files && event.target.files[0];
|
|
390
|
-
if (file)
|
|
391
|
-
this._loadImageFile(file);
|
|
373
|
+
if (file) this._loadImageFile(file);
|
|
392
374
|
});
|
|
393
375
|
this._bindIfExists("zoomInBtn", "click", () => this.scaleImage(this.currentScale + this.options.scaleStep));
|
|
394
376
|
this._bindIfExists("zoomOutBtn", "click", () => this.scaleImage(this.currentScale - this.options.scaleStep));
|
|
@@ -407,8 +389,7 @@ var ImageEditor = class {
|
|
|
407
389
|
let step = this.options.rotationStep;
|
|
408
390
|
if (rotationInputElement) {
|
|
409
391
|
const parsedStep = parseFloat(rotationInputElement.value);
|
|
410
|
-
if (!isNaN(parsedStep))
|
|
411
|
-
step = parsedStep;
|
|
392
|
+
if (!isNaN(parsedStep)) step = parsedStep;
|
|
412
393
|
}
|
|
413
394
|
this.rotateImage(this.currentRotation - step);
|
|
414
395
|
});
|
|
@@ -417,8 +398,7 @@ var ImageEditor = class {
|
|
|
417
398
|
let step = this.options.rotationStep;
|
|
418
399
|
if (rotationInputElement) {
|
|
419
400
|
const parsedStep = parseFloat(rotationInputElement.value);
|
|
420
|
-
if (!isNaN(parsedStep))
|
|
421
|
-
step = parsedStep;
|
|
401
|
+
if (!isNaN(parsedStep)) step = parsedStep;
|
|
422
402
|
}
|
|
423
403
|
this.rotateImage(this.currentRotation + step);
|
|
424
404
|
});
|
|
@@ -441,8 +421,7 @@ var ImageEditor = class {
|
|
|
441
421
|
if (element) {
|
|
442
422
|
element.addEventListener(eventName, handler);
|
|
443
423
|
this._handlersByElementKey = this._handlersByElementKey || {};
|
|
444
|
-
if (!this._handlersByElementKey[key])
|
|
445
|
-
this._handlersByElementKey[key] = [];
|
|
424
|
+
if (!this._handlersByElementKey[key]) this._handlersByElementKey[key] = [];
|
|
446
425
|
this._handlersByElementKey[key].push({ eventName, handler });
|
|
447
426
|
}
|
|
448
427
|
}
|
|
@@ -453,8 +432,7 @@ var ImageEditor = class {
|
|
|
453
432
|
* @private
|
|
454
433
|
*/
|
|
455
434
|
_loadImageFile(file) {
|
|
456
|
-
if (!file || !file.type.startsWith("image/"))
|
|
457
|
-
return;
|
|
435
|
+
if (!file || !file.type.startsWith("image/")) return;
|
|
458
436
|
const reader = new FileReader();
|
|
459
437
|
reader.onload = (event) => this.loadImage(event.target.result);
|
|
460
438
|
reader.onerror = (event) => {
|
|
@@ -474,8 +452,7 @@ var ImageEditor = class {
|
|
|
474
452
|
["coverImageToCanvas", this.options.coverImageToCanvas],
|
|
475
453
|
["expandCanvasToImage", this.options.expandCanvasToImage]
|
|
476
454
|
].filter(([, isEnabled]) => !!isEnabled).map(([name]) => name);
|
|
477
|
-
if (activeModes.length <= 1)
|
|
478
|
-
return;
|
|
455
|
+
if (activeModes.length <= 1) return;
|
|
479
456
|
this._reportWarning(
|
|
480
457
|
`Only one image layout mode should be enabled. Active modes: ${activeModes.join(", ")}.`
|
|
481
458
|
);
|
|
@@ -490,12 +467,9 @@ var ImageEditor = class {
|
|
|
490
467
|
* @public
|
|
491
468
|
*/
|
|
492
469
|
async loadImage(imageBase64, options = {}) {
|
|
493
|
-
if (!this._fabricLoaded)
|
|
494
|
-
|
|
495
|
-
if (!
|
|
496
|
-
return;
|
|
497
|
-
if (!imageBase64 || typeof imageBase64 !== "string" || !imageBase64.startsWith("data:image/"))
|
|
498
|
-
return;
|
|
470
|
+
if (!this._fabricLoaded) return;
|
|
471
|
+
if (!this.canvas) return;
|
|
472
|
+
if (!imageBase64 || typeof imageBase64 !== "string" || !imageBase64.startsWith("data:image/")) return;
|
|
499
473
|
this._warnOnImageLayoutOptionConflict();
|
|
500
474
|
this._setPlaceholderVisible(false);
|
|
501
475
|
this._syncContainerOverflow({ preserveScroll: options.preserveScroll === true });
|
|
@@ -516,8 +490,7 @@ var ImageEditor = class {
|
|
|
516
490
|
return new Promise((resolve, reject) => {
|
|
517
491
|
fabric.Image.fromURL(loadSource, (fabricImage) => {
|
|
518
492
|
try {
|
|
519
|
-
if (!fabricImage)
|
|
520
|
-
throw new Error("Image could not be loaded");
|
|
493
|
+
if (!fabricImage) throw new Error("Image could not be loaded");
|
|
521
494
|
this.canvas.discardActiveObject();
|
|
522
495
|
this._hideAllMaskLabels();
|
|
523
496
|
this.canvas.clear();
|
|
@@ -611,8 +584,7 @@ var ImageEditor = class {
|
|
|
611
584
|
const safeTimeoutMs = Number.isFinite(Number(timeoutMs)) && Number(timeoutMs) > 0 ? Number(timeoutMs) : 3e4;
|
|
612
585
|
let timerId;
|
|
613
586
|
const settle = (callback) => {
|
|
614
|
-
if (isSettled)
|
|
615
|
-
return;
|
|
587
|
+
if (isSettled) return;
|
|
616
588
|
isSettled = true;
|
|
617
589
|
clearTimeout(timerId);
|
|
618
590
|
imageElement.onload = null;
|
|
@@ -624,6 +596,7 @@ var ImageEditor = class {
|
|
|
624
596
|
try {
|
|
625
597
|
imageElement.src = "";
|
|
626
598
|
} catch (error) {
|
|
599
|
+
void error;
|
|
627
600
|
}
|
|
628
601
|
}, safeTimeoutMs);
|
|
629
602
|
imageElement.onload = () => settle(() => resolve(imageElement));
|
|
@@ -646,8 +619,7 @@ var ImageEditor = class {
|
|
|
646
619
|
offscreenCanvas.width = targetWidth;
|
|
647
620
|
offscreenCanvas.height = targetHeight;
|
|
648
621
|
const context = offscreenCanvas.getContext("2d");
|
|
649
|
-
if (!context)
|
|
650
|
-
throw new Error("2D canvas context is unavailable");
|
|
622
|
+
if (!context) throw new Error("2D canvas context is unavailable");
|
|
651
623
|
context.drawImage(imageElement, 0, 0, imageElement.naturalWidth, imageElement.naturalHeight, 0, 0, targetWidth, targetHeight);
|
|
652
624
|
return offscreenCanvas.toDataURL("image/jpeg", quality);
|
|
653
625
|
}
|
|
@@ -664,8 +636,7 @@ var ImageEditor = class {
|
|
|
664
636
|
const integerHeight = Math.max(1, Math.round(Number(height) || 1));
|
|
665
637
|
this.canvas.setWidth(integerWidth);
|
|
666
638
|
this.canvas.setHeight(integerHeight);
|
|
667
|
-
if (typeof this.canvas.calcOffset === "function")
|
|
668
|
-
this.canvas.calcOffset();
|
|
639
|
+
if (typeof this.canvas.calcOffset === "function") this.canvas.calcOffset();
|
|
669
640
|
if (this.canvasElement) {
|
|
670
641
|
this.canvasElement.style.width = integerWidth + "px";
|
|
671
642
|
this.canvasElement.style.height = integerHeight + "px";
|
|
@@ -675,8 +646,7 @@ var ImageEditor = class {
|
|
|
675
646
|
_ceilCanvasDimension(value) {
|
|
676
647
|
const numericValue = Number(value) || 0;
|
|
677
648
|
const roundedValue = Math.round(numericValue);
|
|
678
|
-
if (Math.abs(numericValue - roundedValue) < 0.01)
|
|
679
|
-
return roundedValue;
|
|
649
|
+
if (Math.abs(numericValue - roundedValue) < 0.01) return roundedValue;
|
|
680
650
|
return Math.ceil(numericValue);
|
|
681
651
|
}
|
|
682
652
|
_getContainerViewportSize() {
|
|
@@ -686,19 +656,31 @@ var ImageEditor = class {
|
|
|
686
656
|
height: Math.max(1, Math.floor(this.options.canvasHeight || 1))
|
|
687
657
|
};
|
|
688
658
|
}
|
|
659
|
+
let width = Math.max(1, Math.floor(this.containerElement.clientWidth || this.options.canvasWidth || 1));
|
|
660
|
+
let height = Math.max(1, Math.floor(this.containerElement.clientHeight || this.options.canvasHeight || 1));
|
|
689
661
|
if (this._hasFixedContainerScrollbars()) {
|
|
690
|
-
return {
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
662
|
+
return { width, height };
|
|
663
|
+
}
|
|
664
|
+
const overflow = this._getContainerOverflowValues();
|
|
665
|
+
const canScrollX = overflow.x.some((value) => value === "auto" || value === "scroll");
|
|
666
|
+
const canScrollY = overflow.y.some((value) => value === "auto" || value === "scroll");
|
|
667
|
+
const hasHorizontalScrollbar = canScrollX && this.containerElement.scrollWidth > this.containerElement.clientWidth;
|
|
668
|
+
const hasVerticalScrollbar = canScrollY && this.containerElement.scrollHeight > this.containerElement.clientHeight;
|
|
669
|
+
if (hasHorizontalScrollbar || hasVerticalScrollbar) {
|
|
670
|
+
const scrollbar = this._getScrollbarSize();
|
|
671
|
+
if (hasVerticalScrollbar) width += scrollbar.width;
|
|
672
|
+
if (hasHorizontalScrollbar) height += scrollbar.height;
|
|
694
673
|
}
|
|
695
|
-
const width = Math.max(1, Math.floor(this.containerElement.clientWidth || this.options.canvasWidth || 1));
|
|
696
|
-
const height = Math.max(1, Math.floor(this.containerElement.clientHeight || this.options.canvasHeight || 1));
|
|
697
674
|
return { width, height };
|
|
698
675
|
}
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
676
|
+
/**
|
|
677
|
+
* Reads inline and computed overflow values for both scroll axes.
|
|
678
|
+
*
|
|
679
|
+
* @returns {{x:string[], y:string[]}} Overflow values grouped by axis.
|
|
680
|
+
* @private
|
|
681
|
+
*/
|
|
682
|
+
_getContainerOverflowValues() {
|
|
683
|
+
if (!this.containerElement) return { x: [], y: [] };
|
|
702
684
|
const inlineOverflow = this.containerElement.style.overflow;
|
|
703
685
|
const inlineOverflowX = this.containerElement.style.overflowX;
|
|
704
686
|
const inlineOverflowY = this.containerElement.style.overflowY;
|
|
@@ -711,7 +693,15 @@ var ImageEditor = class {
|
|
|
711
693
|
computedOverflowX = style.overflowX;
|
|
712
694
|
computedOverflowY = style.overflowY;
|
|
713
695
|
}
|
|
714
|
-
return
|
|
696
|
+
return {
|
|
697
|
+
x: [inlineOverflow, inlineOverflowX, computedOverflow, computedOverflowX],
|
|
698
|
+
y: [inlineOverflow, inlineOverflowY, computedOverflow, computedOverflowY]
|
|
699
|
+
};
|
|
700
|
+
}
|
|
701
|
+
_hasFixedContainerScrollbars() {
|
|
702
|
+
if (!this.containerElement) return false;
|
|
703
|
+
const overflow = this._getContainerOverflowValues();
|
|
704
|
+
return [...overflow.x, ...overflow.y].some((value) => value === "scroll");
|
|
715
705
|
}
|
|
716
706
|
_getScrollbarSize() {
|
|
717
707
|
if (this._scrollbarSizeCache) {
|
|
@@ -754,15 +744,14 @@ var ImageEditor = class {
|
|
|
754
744
|
const scrollbar = this._getScrollbarSize();
|
|
755
745
|
let hasVertical = false;
|
|
756
746
|
let hasHorizontal = false;
|
|
757
|
-
let effectiveWidth
|
|
758
|
-
let effectiveHeight
|
|
747
|
+
let effectiveWidth;
|
|
748
|
+
let effectiveHeight;
|
|
759
749
|
for (let i = 0; i < 4; i += 1) {
|
|
760
750
|
effectiveWidth = Math.max(1, viewport.width - (hasVertical ? scrollbar.width : 0));
|
|
761
751
|
effectiveHeight = Math.max(1, viewport.height - (hasHorizontal ? scrollbar.height : 0));
|
|
762
752
|
const nextHasVertical = contentHeight > effectiveHeight + 0.5;
|
|
763
753
|
const nextHasHorizontal = contentWidth > effectiveWidth + 0.5;
|
|
764
|
-
if (nextHasVertical === hasVertical && nextHasHorizontal === hasHorizontal)
|
|
765
|
-
break;
|
|
754
|
+
if (nextHasVertical === hasVertical && nextHasHorizontal === hasHorizontal) break;
|
|
766
755
|
hasVertical = nextHasVertical;
|
|
767
756
|
hasHorizontal = nextHasHorizontal;
|
|
768
757
|
}
|
|
@@ -799,8 +788,8 @@ var ImageEditor = class {
|
|
|
799
788
|
let scale = 1;
|
|
800
789
|
let contentWidth = imageWidth;
|
|
801
790
|
let contentHeight = imageHeight;
|
|
802
|
-
let effectiveWidth
|
|
803
|
-
let effectiveHeight
|
|
791
|
+
let effectiveWidth;
|
|
792
|
+
let effectiveHeight;
|
|
804
793
|
for (let i = 0; i < 4; i += 1) {
|
|
805
794
|
effectiveWidth = Math.max(1, viewport.width - (hasVertical ? scrollbar.width : 0));
|
|
806
795
|
effectiveHeight = Math.max(1, viewport.height - (hasHorizontal ? scrollbar.height : 0));
|
|
@@ -809,8 +798,7 @@ var ImageEditor = class {
|
|
|
809
798
|
contentHeight = imageHeight * scale;
|
|
810
799
|
const nextHasVertical = contentHeight > effectiveHeight + 0.5;
|
|
811
800
|
const nextHasHorizontal = contentWidth > effectiveWidth + 0.5;
|
|
812
|
-
if (nextHasVertical === hasVertical && nextHasHorizontal === hasHorizontal)
|
|
813
|
-
break;
|
|
801
|
+
if (nextHasVertical === hasVertical && nextHasHorizontal === hasHorizontal) break;
|
|
814
802
|
hasVertical = nextHasVertical;
|
|
815
803
|
hasHorizontal = nextHasHorizontal;
|
|
816
804
|
}
|
|
@@ -849,41 +837,48 @@ var ImageEditor = class {
|
|
|
849
837
|
stroke: mask && mask.originalStroke || "#ccc",
|
|
850
838
|
strokeWidth: Number.isFinite(strokeWidth) ? strokeWidth : 1
|
|
851
839
|
};
|
|
852
|
-
if (Number.isFinite(opacity))
|
|
853
|
-
style.opacity = opacity;
|
|
840
|
+
if (Number.isFinite(opacity)) style.opacity = opacity;
|
|
854
841
|
return style;
|
|
855
842
|
}
|
|
856
843
|
_withNormalizedMaskStyles(callback) {
|
|
857
|
-
if (!this.canvas)
|
|
858
|
-
return callback();
|
|
844
|
+
if (!this.canvas) return callback();
|
|
859
845
|
const masks = this.canvas.getObjects().filter((object) => object.maskId);
|
|
860
|
-
const maskStyleBackups =
|
|
861
|
-
object: mask,
|
|
862
|
-
stroke: mask.stroke,
|
|
863
|
-
strokeWidth: mask.strokeWidth,
|
|
864
|
-
opacity: mask.opacity
|
|
865
|
-
}));
|
|
846
|
+
const maskStyleBackups = [];
|
|
866
847
|
try {
|
|
867
848
|
masks.forEach((mask) => {
|
|
868
|
-
|
|
849
|
+
const normalStyle = this._getMaskNormalStyle(mask);
|
|
850
|
+
const stylePatch = {};
|
|
851
|
+
Object.keys(normalStyle).forEach((property) => {
|
|
852
|
+
if (mask[property] !== normalStyle[property]) {
|
|
853
|
+
stylePatch[property] = normalStyle[property];
|
|
854
|
+
}
|
|
855
|
+
});
|
|
856
|
+
const changedProperties = Object.keys(stylePatch);
|
|
857
|
+
if (!changedProperties.length) return;
|
|
858
|
+
const backup = { object: mask };
|
|
859
|
+
changedProperties.forEach((property) => {
|
|
860
|
+
backup[property] = mask[property];
|
|
861
|
+
});
|
|
862
|
+
maskStyleBackups.push(backup);
|
|
863
|
+
mask.set(stylePatch);
|
|
869
864
|
});
|
|
870
865
|
return callback();
|
|
871
866
|
} finally {
|
|
872
867
|
maskStyleBackups.forEach((backup) => {
|
|
873
868
|
try {
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
opacity: backup.opacity
|
|
869
|
+
const restorePatch = {};
|
|
870
|
+
Object.keys(backup).forEach((property) => {
|
|
871
|
+
if (property !== "object") restorePatch[property] = backup[property];
|
|
878
872
|
});
|
|
873
|
+
backup.object.set(restorePatch);
|
|
879
874
|
} catch (error) {
|
|
875
|
+
void error;
|
|
880
876
|
}
|
|
881
877
|
});
|
|
882
878
|
}
|
|
883
879
|
}
|
|
884
880
|
_restoreMaskControls(mask) {
|
|
885
|
-
if (!mask)
|
|
886
|
-
return;
|
|
881
|
+
if (!mask) return;
|
|
887
882
|
const cornerSize = Number(mask.cornerSize);
|
|
888
883
|
mask.set({
|
|
889
884
|
selectable: mask.selectable !== false,
|
|
@@ -896,8 +891,7 @@ var ImageEditor = class {
|
|
|
896
891
|
transparentCorners: mask.transparentCorners === true,
|
|
897
892
|
strokeUniform: mask.strokeUniform !== false
|
|
898
893
|
});
|
|
899
|
-
if (typeof mask.setCoords === "function")
|
|
900
|
-
mask.setCoords();
|
|
894
|
+
if (typeof mask.setCoords === "function") mask.setCoords();
|
|
901
895
|
}
|
|
902
896
|
/**
|
|
903
897
|
* Captures editor-owned runtime state that Fabric does not include in canvas JSON.
|
|
@@ -919,8 +913,7 @@ var ImageEditor = class {
|
|
|
919
913
|
};
|
|
920
914
|
}
|
|
921
915
|
_serializeCanvasState() {
|
|
922
|
-
if (!this.canvas)
|
|
923
|
-
return null;
|
|
916
|
+
if (!this.canvas) return null;
|
|
924
917
|
return this._withNormalizedMaskStyles(() => {
|
|
925
918
|
const jsonObject = this.canvas.toJSON(this._getStateProperties());
|
|
926
919
|
if (Array.isArray(jsonObject.objects)) {
|
|
@@ -939,8 +932,7 @@ var ImageEditor = class {
|
|
|
939
932
|
*/
|
|
940
933
|
_normalizeQuality(quality) {
|
|
941
934
|
const numericQuality = Number(quality);
|
|
942
|
-
if (!Number.isFinite(numericQuality))
|
|
943
|
-
return this.options.downsampleQuality ?? 0.92;
|
|
935
|
+
if (!Number.isFinite(numericQuality)) return this.options.downsampleQuality ?? 0.92;
|
|
944
936
|
return Math.max(0, Math.min(1, numericQuality));
|
|
945
937
|
}
|
|
946
938
|
/**
|
|
@@ -1013,8 +1005,7 @@ var ImageEditor = class {
|
|
|
1013
1005
|
const safeTimeoutMs = Number.isFinite(timeoutMs) && timeoutMs > 0 ? timeoutMs : 3e4;
|
|
1014
1006
|
let timerId;
|
|
1015
1007
|
const settle = (callback) => {
|
|
1016
|
-
if (isSettled)
|
|
1017
|
-
return;
|
|
1008
|
+
if (isSettled) return;
|
|
1018
1009
|
isSettled = true;
|
|
1019
1010
|
clearTimeout(timerId);
|
|
1020
1011
|
imageElement.onload = null;
|
|
@@ -1026,6 +1017,7 @@ var ImageEditor = class {
|
|
|
1026
1017
|
try {
|
|
1027
1018
|
imageElement.src = "";
|
|
1028
1019
|
} catch (error) {
|
|
1020
|
+
void error;
|
|
1029
1021
|
}
|
|
1030
1022
|
}, safeTimeoutMs);
|
|
1031
1023
|
imageElement.onload = () => {
|
|
@@ -1039,8 +1031,7 @@ var ImageEditor = class {
|
|
|
1039
1031
|
offscreenCanvas.width = scaledSourceWidth;
|
|
1040
1032
|
offscreenCanvas.height = scaledSourceHeight;
|
|
1041
1033
|
const context = offscreenCanvas.getContext("2d");
|
|
1042
|
-
if (!context)
|
|
1043
|
-
throw new Error("2D canvas context is unavailable");
|
|
1034
|
+
if (!context) throw new Error("2D canvas context is unavailable");
|
|
1044
1035
|
context.drawImage(imageElement, scaledSourceX, scaledSourceY, scaledSourceWidth, scaledSourceHeight, 0, 0, scaledSourceWidth, scaledSourceHeight);
|
|
1045
1036
|
settle(() => resolve(offscreenCanvas.toDataURL(`image/${format}`, quality)));
|
|
1046
1037
|
} catch (error) {
|
|
@@ -1083,12 +1074,10 @@ var ImageEditor = class {
|
|
|
1083
1074
|
* @private
|
|
1084
1075
|
*/
|
|
1085
1076
|
_getObjectTopLeftPoint(fabricObject) {
|
|
1086
|
-
if (!fabricObject)
|
|
1087
|
-
return { x: 0, y: 0 };
|
|
1077
|
+
if (!fabricObject) return { x: 0, y: 0 };
|
|
1088
1078
|
fabricObject.setCoords();
|
|
1089
1079
|
const coords = typeof fabricObject.getCoords === "function" ? fabricObject.getCoords() : null;
|
|
1090
|
-
if (coords && coords.length)
|
|
1091
|
-
return coords[0];
|
|
1080
|
+
if (coords && coords.length) return coords[0];
|
|
1092
1081
|
const boundingRect = fabricObject.getBoundingRect(true, true);
|
|
1093
1082
|
return { x: boundingRect.left, y: boundingRect.top };
|
|
1094
1083
|
}
|
|
@@ -1102,8 +1091,7 @@ var ImageEditor = class {
|
|
|
1102
1091
|
* @private
|
|
1103
1092
|
*/
|
|
1104
1093
|
_setObjectOriginKeepingPosition(fabricObject, originX, originY, refPoint) {
|
|
1105
|
-
if (!fabricObject || !refPoint || !fabricObject.setPositionByOrigin)
|
|
1106
|
-
return;
|
|
1094
|
+
if (!fabricObject || !refPoint || !fabricObject.setPositionByOrigin) return;
|
|
1107
1095
|
fabricObject.set({ originX, originY });
|
|
1108
1096
|
fabricObject.setPositionByOrigin(refPoint, originX, originY);
|
|
1109
1097
|
fabricObject.setCoords();
|
|
@@ -1115,8 +1103,7 @@ var ImageEditor = class {
|
|
|
1115
1103
|
* @private
|
|
1116
1104
|
*/
|
|
1117
1105
|
_alignObjectBoundingBoxToCanvasTopLeft(fabricObject) {
|
|
1118
|
-
if (!fabricObject)
|
|
1119
|
-
return;
|
|
1106
|
+
if (!fabricObject) return;
|
|
1120
1107
|
fabricObject.setCoords();
|
|
1121
1108
|
const boundingRect = fabricObject.getBoundingRect(true, true);
|
|
1122
1109
|
const deltaX = boundingRect.left;
|
|
@@ -1131,8 +1118,7 @@ var ImageEditor = class {
|
|
|
1131
1118
|
* @private
|
|
1132
1119
|
*/
|
|
1133
1120
|
_updateCanvasSizeToImageBounds() {
|
|
1134
|
-
if (!this.originalImage)
|
|
1135
|
-
return;
|
|
1121
|
+
if (!this.originalImage) return;
|
|
1136
1122
|
this.originalImage.setCoords();
|
|
1137
1123
|
const imageBounds = this.originalImage.getBoundingRect(true, true);
|
|
1138
1124
|
const size = this._getScrollableCanvasSize(imageBounds.width, imageBounds.height);
|
|
@@ -1156,16 +1142,13 @@ var ImageEditor = class {
|
|
|
1156
1142
|
* @private
|
|
1157
1143
|
*/
|
|
1158
1144
|
_expandCanvasToFitObjects(fabricObjects, padding = 10) {
|
|
1159
|
-
if (!this.canvas || !Array.isArray(fabricObjects) || !fabricObjects.length || !this._shouldResizeCanvasToContentBounds())
|
|
1160
|
-
return;
|
|
1145
|
+
if (!this.canvas || !Array.isArray(fabricObjects) || !fabricObjects.length || !this._shouldResizeCanvasToContentBounds()) return;
|
|
1161
1146
|
try {
|
|
1162
1147
|
let requiredWidth = this.canvas.getWidth();
|
|
1163
1148
|
let requiredHeight = this.canvas.getHeight();
|
|
1164
1149
|
fabricObjects.forEach((fabricObject) => {
|
|
1165
|
-
if (!fabricObject)
|
|
1166
|
-
|
|
1167
|
-
if (typeof fabricObject.setCoords === "function")
|
|
1168
|
-
fabricObject.setCoords();
|
|
1150
|
+
if (!fabricObject) return;
|
|
1151
|
+
if (typeof fabricObject.setCoords === "function") fabricObject.setCoords();
|
|
1169
1152
|
const boundingRect = fabricObject.getBoundingRect(true, true);
|
|
1170
1153
|
requiredWidth = Math.max(requiredWidth, Math.ceil(boundingRect.left + boundingRect.width + padding));
|
|
1171
1154
|
requiredHeight = Math.max(requiredHeight, Math.ceil(boundingRect.top + boundingRect.height + padding));
|
|
@@ -1210,10 +1193,8 @@ var ImageEditor = class {
|
|
|
1210
1193
|
* @private
|
|
1211
1194
|
*/
|
|
1212
1195
|
_scaleImageImpl(factor, options = {}) {
|
|
1213
|
-
if (!this.originalImage)
|
|
1214
|
-
|
|
1215
|
-
if (this.isAnimating)
|
|
1216
|
-
return Promise.resolve();
|
|
1196
|
+
if (!this.originalImage) return Promise.resolve();
|
|
1197
|
+
if (this.isAnimating) return Promise.resolve();
|
|
1217
1198
|
const saveHistory = options.saveHistory !== false;
|
|
1218
1199
|
factor = Math.max(this.options.minScale, Math.min(this.options.maxScale, factor));
|
|
1219
1200
|
this.currentScale = factor;
|
|
@@ -1244,14 +1225,12 @@ var ImageEditor = class {
|
|
|
1244
1225
|
}
|
|
1245
1226
|
this._alignObjectBoundingBoxToCanvasTopLeft(this.originalImage);
|
|
1246
1227
|
this.canvas.getObjects().forEach((object) => {
|
|
1247
|
-
if (object.maskId)
|
|
1248
|
-
this._syncMaskLabel(object);
|
|
1228
|
+
if (object.maskId) this._syncMaskLabel(object);
|
|
1249
1229
|
});
|
|
1250
1230
|
this.isAnimating = false;
|
|
1251
1231
|
this._updateInputs();
|
|
1252
1232
|
this._updateUI();
|
|
1253
|
-
if (saveHistory)
|
|
1254
|
-
this.saveState();
|
|
1233
|
+
if (saveHistory) this.saveState();
|
|
1255
1234
|
}).catch(() => {
|
|
1256
1235
|
this.isAnimating = false;
|
|
1257
1236
|
this._updateUI();
|
|
@@ -1275,12 +1254,9 @@ var ImageEditor = class {
|
|
|
1275
1254
|
* @private
|
|
1276
1255
|
*/
|
|
1277
1256
|
_rotateImageImpl(degrees, options = {}) {
|
|
1278
|
-
if (!this.originalImage)
|
|
1279
|
-
|
|
1280
|
-
if (
|
|
1281
|
-
return Promise.resolve();
|
|
1282
|
-
if (isNaN(degrees))
|
|
1283
|
-
return Promise.resolve();
|
|
1257
|
+
if (!this.originalImage) return Promise.resolve();
|
|
1258
|
+
if (this.isAnimating) return Promise.resolve();
|
|
1259
|
+
if (isNaN(degrees)) return Promise.resolve();
|
|
1284
1260
|
const saveHistory = options.saveHistory !== false;
|
|
1285
1261
|
this.currentRotation = degrees;
|
|
1286
1262
|
this.isAnimating = true;
|
|
@@ -1304,14 +1280,12 @@ var ImageEditor = class {
|
|
|
1304
1280
|
const newTopLeft = this._getObjectTopLeftPoint(this.originalImage);
|
|
1305
1281
|
this._setObjectOriginKeepingPosition(this.originalImage, "left", "top", newTopLeft);
|
|
1306
1282
|
this.canvas.getObjects().forEach((object) => {
|
|
1307
|
-
if (object.maskId)
|
|
1308
|
-
this._syncMaskLabel(object);
|
|
1283
|
+
if (object.maskId) this._syncMaskLabel(object);
|
|
1309
1284
|
});
|
|
1310
1285
|
this.isAnimating = false;
|
|
1311
1286
|
this._updateInputs();
|
|
1312
1287
|
this._updateUI();
|
|
1313
|
-
if (saveHistory)
|
|
1314
|
-
this.saveState();
|
|
1288
|
+
if (saveHistory) this.saveState();
|
|
1315
1289
|
}).catch(() => {
|
|
1316
1290
|
this.isAnimating = false;
|
|
1317
1291
|
this._updateUI();
|
|
@@ -1324,8 +1298,7 @@ var ImageEditor = class {
|
|
|
1324
1298
|
* @public
|
|
1325
1299
|
*/
|
|
1326
1300
|
resetImageTransform() {
|
|
1327
|
-
if (!this.originalImage)
|
|
1328
|
-
return Promise.resolve();
|
|
1301
|
+
if (!this.originalImage) return Promise.resolve();
|
|
1329
1302
|
return this.animationQueue.add(async () => {
|
|
1330
1303
|
const before = this._lastSnapshot || this._serializeCanvasState();
|
|
1331
1304
|
await this._scaleImageImpl(1, { saveHistory: false });
|
|
@@ -1353,8 +1326,7 @@ var ImageEditor = class {
|
|
|
1353
1326
|
* @public
|
|
1354
1327
|
*/
|
|
1355
1328
|
loadFromState(serializedState) {
|
|
1356
|
-
if (!serializedState || !this.canvas)
|
|
1357
|
-
return Promise.resolve();
|
|
1329
|
+
if (!serializedState || !this.canvas) return Promise.resolve();
|
|
1358
1330
|
return new Promise((resolve) => {
|
|
1359
1331
|
try {
|
|
1360
1332
|
const state = typeof serializedState === "string" ? JSON.parse(serializedState) : serializedState;
|
|
@@ -1430,14 +1402,12 @@ var ImageEditor = class {
|
|
|
1430
1402
|
* @public
|
|
1431
1403
|
*/
|
|
1432
1404
|
saveState() {
|
|
1433
|
-
if (!this.canvas)
|
|
1434
|
-
return;
|
|
1405
|
+
if (!this.canvas) return;
|
|
1435
1406
|
const activeObject = this.canvas.getActiveObject();
|
|
1436
1407
|
try {
|
|
1437
1408
|
const after = this._serializeCanvasState();
|
|
1438
1409
|
const before = this._lastSnapshot || after;
|
|
1439
|
-
if (after === before)
|
|
1440
|
-
return;
|
|
1410
|
+
if (after === before) return;
|
|
1441
1411
|
let executedOnce = false;
|
|
1442
1412
|
const command = new Command(
|
|
1443
1413
|
() => {
|
|
@@ -1472,12 +1442,9 @@ var ImageEditor = class {
|
|
|
1472
1442
|
* @private
|
|
1473
1443
|
*/
|
|
1474
1444
|
_pushStateTransition(before, after) {
|
|
1475
|
-
if (!before || !after)
|
|
1476
|
-
|
|
1477
|
-
if (
|
|
1478
|
-
return;
|
|
1479
|
-
if (!this.historyManager)
|
|
1480
|
-
this.historyManager = new HistoryManager(this.maxHistorySize || 50);
|
|
1445
|
+
if (!before || !after) return;
|
|
1446
|
+
if (before === after) return;
|
|
1447
|
+
if (!this.historyManager) this.historyManager = new HistoryManager(this.maxHistorySize || 50);
|
|
1481
1448
|
const command = new Command(
|
|
1482
1449
|
() => this.loadFromState(after),
|
|
1483
1450
|
() => this.loadFromState(before)
|
|
@@ -1513,26 +1480,24 @@ var ImageEditor = class {
|
|
|
1513
1480
|
});
|
|
1514
1481
|
}
|
|
1515
1482
|
_rebindMaskEvents(mask) {
|
|
1516
|
-
if (!mask)
|
|
1517
|
-
return;
|
|
1483
|
+
if (!mask) return;
|
|
1518
1484
|
if (mask.__imageEditorMaskHandlers) {
|
|
1519
1485
|
try {
|
|
1520
1486
|
mask.off("mouseover", mask.__imageEditorMaskHandlers.mouseover);
|
|
1521
1487
|
mask.off("mouseout", mask.__imageEditorMaskHandlers.mouseout);
|
|
1522
1488
|
} catch (error) {
|
|
1489
|
+
void error;
|
|
1523
1490
|
}
|
|
1524
1491
|
}
|
|
1525
1492
|
const metadata = {};
|
|
1526
1493
|
if (!Number.isFinite(Number(mask.originalAlpha))) {
|
|
1527
1494
|
metadata.originalAlpha = Number.isFinite(Number(mask.opacity)) ? Number(mask.opacity) : 0.5;
|
|
1528
1495
|
}
|
|
1529
|
-
if (!mask.originalStroke)
|
|
1530
|
-
metadata.originalStroke = mask.stroke || "#ccc";
|
|
1496
|
+
if (!mask.originalStroke) metadata.originalStroke = mask.stroke || "#ccc";
|
|
1531
1497
|
if (!Number.isFinite(Number(mask.originalStrokeWidth))) {
|
|
1532
1498
|
metadata.originalStrokeWidth = Number.isFinite(Number(mask.strokeWidth)) ? Number(mask.strokeWidth) : 1;
|
|
1533
1499
|
}
|
|
1534
|
-
if (Object.keys(metadata).length)
|
|
1535
|
-
mask.set(metadata);
|
|
1500
|
+
if (Object.keys(metadata).length) mask.set(metadata);
|
|
1536
1501
|
const normalStyle = {
|
|
1537
1502
|
stroke: mask.originalStroke || "#ccc",
|
|
1538
1503
|
strokeWidth: mask.originalStrokeWidth,
|
|
@@ -1545,13 +1510,11 @@ var ImageEditor = class {
|
|
|
1545
1510
|
};
|
|
1546
1511
|
const mouseover = () => {
|
|
1547
1512
|
mask.set(hoverStyle);
|
|
1548
|
-
if (mask.canvas)
|
|
1549
|
-
mask.canvas.requestRenderAll();
|
|
1513
|
+
if (mask.canvas) mask.canvas.requestRenderAll();
|
|
1550
1514
|
};
|
|
1551
1515
|
const mouseout = () => {
|
|
1552
1516
|
mask.set(normalStyle);
|
|
1553
|
-
if (mask.canvas)
|
|
1554
|
-
mask.canvas.requestRenderAll();
|
|
1517
|
+
if (mask.canvas) mask.canvas.requestRenderAll();
|
|
1555
1518
|
};
|
|
1556
1519
|
mask.on("mouseover", mouseover);
|
|
1557
1520
|
mask.on("mouseout", mouseout);
|
|
@@ -1586,8 +1549,7 @@ var ImageEditor = class {
|
|
|
1586
1549
|
* @public
|
|
1587
1550
|
*/
|
|
1588
1551
|
createMask(config = {}) {
|
|
1589
|
-
if (!this.canvas)
|
|
1590
|
-
return null;
|
|
1552
|
+
if (!this.canvas) return null;
|
|
1591
1553
|
const shapeType = config.shape || "rect";
|
|
1592
1554
|
const maskConfig = {
|
|
1593
1555
|
shape: shapeType,
|
|
@@ -1603,14 +1565,22 @@ var ImageEditor = class {
|
|
|
1603
1565
|
...config
|
|
1604
1566
|
};
|
|
1605
1567
|
const firstOffset = 10;
|
|
1606
|
-
let left
|
|
1607
|
-
let top
|
|
1608
|
-
const
|
|
1568
|
+
let left;
|
|
1569
|
+
let top;
|
|
1570
|
+
const getCanvasBasis = (axis) => {
|
|
1571
|
+
const canvasWidth = this.canvas ? this.canvas.getWidth() : 0;
|
|
1572
|
+
const canvasHeight = this.canvas ? this.canvas.getHeight() : 0;
|
|
1573
|
+
if (axis === "height") return canvasHeight;
|
|
1574
|
+
if (axis === "min") return Math.min(canvasWidth, canvasHeight);
|
|
1575
|
+
return canvasWidth;
|
|
1576
|
+
};
|
|
1577
|
+
const resolveValue = (value, fallback, axis = "width") => {
|
|
1609
1578
|
if (typeof value === "function")
|
|
1610
1579
|
return value(this.canvas, this.options);
|
|
1611
1580
|
if (typeof value === "string" && value.endsWith("%")) {
|
|
1612
|
-
const percent = parseFloat(value) / 100;
|
|
1613
|
-
|
|
1581
|
+
const percent = Number.parseFloat(value) / 100;
|
|
1582
|
+
if (!Number.isFinite(percent)) return fallback;
|
|
1583
|
+
return Math.floor(getCanvasBasis(axis) * percent);
|
|
1614
1584
|
}
|
|
1615
1585
|
return value != null ? value : fallback;
|
|
1616
1586
|
};
|
|
@@ -1625,11 +1595,11 @@ var ImageEditor = class {
|
|
|
1625
1595
|
left = Math.round(previousMaskRight + maskConfig.gap);
|
|
1626
1596
|
top = previousMask.top ?? firstOffset;
|
|
1627
1597
|
} else {
|
|
1628
|
-
left = resolveValue(maskConfig.left, firstOffset);
|
|
1629
|
-
top = resolveValue(maskConfig.top, firstOffset);
|
|
1598
|
+
left = resolveValue(maskConfig.left, firstOffset, "width");
|
|
1599
|
+
top = resolveValue(maskConfig.top, firstOffset, "height");
|
|
1630
1600
|
}
|
|
1631
|
-
maskConfig.width = resolveValue(maskConfig.width, this.options.defaultMaskWidth);
|
|
1632
|
-
maskConfig.height = resolveValue(maskConfig.height, this.options.defaultMaskHeight);
|
|
1601
|
+
maskConfig.width = resolveValue(maskConfig.width, this.options.defaultMaskWidth, "width");
|
|
1602
|
+
maskConfig.height = resolveValue(maskConfig.height, this.options.defaultMaskHeight, "height");
|
|
1633
1603
|
maskConfig.left = left;
|
|
1634
1604
|
maskConfig.top = top;
|
|
1635
1605
|
let mask;
|
|
@@ -1641,7 +1611,7 @@ var ImageEditor = class {
|
|
|
1641
1611
|
mask = new fabric.Circle({
|
|
1642
1612
|
left,
|
|
1643
1613
|
top,
|
|
1644
|
-
radius: resolveValue(maskConfig.radius, Math.min(maskConfig.width, maskConfig.height) / 2),
|
|
1614
|
+
radius: resolveValue(maskConfig.radius, Math.min(maskConfig.width, maskConfig.height) / 2, "min"),
|
|
1645
1615
|
fill: maskConfig.color,
|
|
1646
1616
|
opacity: maskConfig.alpha,
|
|
1647
1617
|
angle: maskConfig.angle,
|
|
@@ -1652,8 +1622,8 @@ var ImageEditor = class {
|
|
|
1652
1622
|
mask = new fabric.Ellipse({
|
|
1653
1623
|
left,
|
|
1654
1624
|
top,
|
|
1655
|
-
rx: resolveValue(maskConfig.rx, maskConfig.width / 2),
|
|
1656
|
-
ry: resolveValue(maskConfig.ry, maskConfig.height / 2),
|
|
1625
|
+
rx: resolveValue(maskConfig.rx, maskConfig.width / 2, "width"),
|
|
1626
|
+
ry: resolveValue(maskConfig.ry, maskConfig.height / 2, "height"),
|
|
1657
1627
|
fill: maskConfig.color,
|
|
1658
1628
|
opacity: maskConfig.alpha,
|
|
1659
1629
|
angle: maskConfig.angle,
|
|
@@ -1680,8 +1650,8 @@ var ImageEditor = class {
|
|
|
1680
1650
|
mask = new fabric.Rect({
|
|
1681
1651
|
left,
|
|
1682
1652
|
top,
|
|
1683
|
-
width: resolveValue(maskConfig.width, this.options.defaultMaskWidth),
|
|
1684
|
-
height: resolveValue(maskConfig.height, this.options.defaultMaskHeight),
|
|
1653
|
+
width: resolveValue(maskConfig.width, this.options.defaultMaskWidth, "width"),
|
|
1654
|
+
height: resolveValue(maskConfig.height, this.options.defaultMaskHeight, "height"),
|
|
1685
1655
|
fill: maskConfig.color,
|
|
1686
1656
|
opacity: maskConfig.alpha,
|
|
1687
1657
|
angle: maskConfig.angle,
|
|
@@ -1706,8 +1676,7 @@ var ImageEditor = class {
|
|
|
1706
1676
|
opacity: hasStyle("opacity") ? styles.opacity : maskConfig.alpha,
|
|
1707
1677
|
strokeUniform: "strokeUniform" in maskConfig ? maskConfig.strokeUniform : hasStyle("strokeUniform") ? styles.strokeUniform : true
|
|
1708
1678
|
};
|
|
1709
|
-
if (hasStyle("strokeDashArray"))
|
|
1710
|
-
maskSettings.strokeDashArray = styles.strokeDashArray;
|
|
1679
|
+
if (hasStyle("strokeDashArray")) maskSettings.strokeDashArray = styles.strokeDashArray;
|
|
1711
1680
|
mask.set(maskSettings);
|
|
1712
1681
|
mask.setCoords();
|
|
1713
1682
|
mask.set({
|
|
@@ -1719,7 +1688,7 @@ var ImageEditor = class {
|
|
|
1719
1688
|
this._expandCanvasToFitObject(mask);
|
|
1720
1689
|
this._lastMaskInitialLeft = left;
|
|
1721
1690
|
this._lastMaskInitialTop = top;
|
|
1722
|
-
this._lastMaskInitialWidth = resolveValue(maskConfig.width, this.options.defaultMaskWidth);
|
|
1691
|
+
this._lastMaskInitialWidth = resolveValue(maskConfig.width, this.options.defaultMaskWidth, "width");
|
|
1723
1692
|
const maskId = ++this.maskCounter;
|
|
1724
1693
|
mask.set({
|
|
1725
1694
|
maskId,
|
|
@@ -1728,15 +1697,13 @@ var ImageEditor = class {
|
|
|
1728
1697
|
this._lastMask = mask;
|
|
1729
1698
|
this.canvas.add(mask);
|
|
1730
1699
|
this.canvas.bringToFront(mask);
|
|
1731
|
-
if (maskConfig.selectable)
|
|
1732
|
-
this.canvas.setActiveObject(mask);
|
|
1700
|
+
if (maskConfig.selectable) this.canvas.setActiveObject(mask);
|
|
1733
1701
|
this._handleSelectionChanged([mask]);
|
|
1734
1702
|
this._updateMaskList();
|
|
1735
1703
|
this._updateUI();
|
|
1736
1704
|
this.canvas.renderAll();
|
|
1737
1705
|
this.saveState();
|
|
1738
|
-
if (typeof maskConfig.onCreate === "function")
|
|
1739
|
-
maskConfig.onCreate(mask, this.canvas);
|
|
1706
|
+
if (typeof maskConfig.onCreate === "function") maskConfig.onCreate(mask, this.canvas);
|
|
1740
1707
|
return mask;
|
|
1741
1708
|
}
|
|
1742
1709
|
/**
|
|
@@ -1756,8 +1723,7 @@ var ImageEditor = class {
|
|
|
1756
1723
|
removeSelectedMask() {
|
|
1757
1724
|
const activeObject = this.canvas.getActiveObject();
|
|
1758
1725
|
const selectedMasks = this._getModifiedMasks(activeObject);
|
|
1759
|
-
if (!selectedMasks.length)
|
|
1760
|
-
return;
|
|
1726
|
+
if (!selectedMasks.length) return;
|
|
1761
1727
|
this.canvas.discardActiveObject();
|
|
1762
1728
|
selectedMasks.forEach((mask) => {
|
|
1763
1729
|
this._removeLabelForMask(mask);
|
|
@@ -1792,8 +1758,7 @@ var ImageEditor = class {
|
|
|
1792
1758
|
this._updateMaskList();
|
|
1793
1759
|
this._updateUI();
|
|
1794
1760
|
this.canvas.renderAll();
|
|
1795
|
-
if (saveHistory)
|
|
1796
|
-
this.saveState();
|
|
1761
|
+
if (saveHistory) this.saveState();
|
|
1797
1762
|
}
|
|
1798
1763
|
/**
|
|
1799
1764
|
* Removes the label associated with the specified mask object, if it exists.
|
|
@@ -1802,8 +1767,7 @@ var ImageEditor = class {
|
|
|
1802
1767
|
* @private
|
|
1803
1768
|
*/
|
|
1804
1769
|
_removeLabelForMask(mask) {
|
|
1805
|
-
if (!mask || !this.canvas)
|
|
1806
|
-
return;
|
|
1770
|
+
if (!mask || !this.canvas) return;
|
|
1807
1771
|
if (mask.__label) {
|
|
1808
1772
|
try {
|
|
1809
1773
|
const canvasObjects = this.canvas.getObjects();
|
|
@@ -1811,10 +1775,12 @@ var ImageEditor = class {
|
|
|
1811
1775
|
this.canvas.remove(mask.__label);
|
|
1812
1776
|
}
|
|
1813
1777
|
} catch (error) {
|
|
1778
|
+
void error;
|
|
1814
1779
|
}
|
|
1815
1780
|
try {
|
|
1816
1781
|
delete mask.__label;
|
|
1817
1782
|
} catch (error) {
|
|
1783
|
+
void error;
|
|
1818
1784
|
}
|
|
1819
1785
|
}
|
|
1820
1786
|
}
|
|
@@ -1830,8 +1796,7 @@ var ImageEditor = class {
|
|
|
1830
1796
|
*/
|
|
1831
1797
|
_getMaskCreationIndex(mask) {
|
|
1832
1798
|
const maskId = Number(mask && mask.maskId);
|
|
1833
|
-
if (Number.isFinite(maskId) && maskId > 0)
|
|
1834
|
-
return Math.floor(maskId) - 1;
|
|
1799
|
+
if (Number.isFinite(maskId) && maskId > 0) return Math.floor(maskId) - 1;
|
|
1835
1800
|
const masks = this.canvas ? this.canvas.getObjects().filter((object) => object.maskId) : [];
|
|
1836
1801
|
return Math.max(0, masks.indexOf(mask));
|
|
1837
1802
|
}
|
|
@@ -1843,8 +1808,7 @@ var ImageEditor = class {
|
|
|
1843
1808
|
* @private
|
|
1844
1809
|
*/
|
|
1845
1810
|
_createLabelForMask(mask) {
|
|
1846
|
-
if (!mask || !this.options.maskLabelOnSelect)
|
|
1847
|
-
return;
|
|
1811
|
+
if (!mask || !this.options.maskLabelOnSelect) return;
|
|
1848
1812
|
this._removeLabelForMask(mask);
|
|
1849
1813
|
let textObject = null;
|
|
1850
1814
|
if (this.options.label && typeof this.options.label.create === "function") {
|
|
@@ -1886,15 +1850,14 @@ var ImageEditor = class {
|
|
|
1886
1850
|
* @private
|
|
1887
1851
|
*/
|
|
1888
1852
|
_hideAllMaskLabels() {
|
|
1889
|
-
if (!this.canvas)
|
|
1890
|
-
return;
|
|
1853
|
+
if (!this.canvas) return;
|
|
1891
1854
|
const canvasObjects = this.canvas.getObjects();
|
|
1892
1855
|
const labels = canvasObjects.filter((object) => object.maskLabel);
|
|
1893
1856
|
labels.forEach((label) => {
|
|
1894
1857
|
try {
|
|
1895
|
-
if (canvasObjects.includes(label))
|
|
1896
|
-
this.canvas.remove(label);
|
|
1858
|
+
if (canvasObjects.includes(label)) this.canvas.remove(label);
|
|
1897
1859
|
} catch (error) {
|
|
1860
|
+
void error;
|
|
1898
1861
|
}
|
|
1899
1862
|
});
|
|
1900
1863
|
canvasObjects.forEach((object) => {
|
|
@@ -1902,6 +1865,7 @@ var ImageEditor = class {
|
|
|
1902
1865
|
try {
|
|
1903
1866
|
delete object.__label;
|
|
1904
1867
|
} catch (error) {
|
|
1868
|
+
void error;
|
|
1905
1869
|
}
|
|
1906
1870
|
}
|
|
1907
1871
|
});
|
|
@@ -1913,15 +1877,11 @@ var ImageEditor = class {
|
|
|
1913
1877
|
* @private
|
|
1914
1878
|
*/
|
|
1915
1879
|
_syncMaskLabel(mask) {
|
|
1916
|
-
if (!mask)
|
|
1917
|
-
|
|
1918
|
-
if (!
|
|
1919
|
-
return;
|
|
1920
|
-
if (!mask.__label)
|
|
1921
|
-
return;
|
|
1880
|
+
if (!mask) return;
|
|
1881
|
+
if (!this.options.maskLabelOnSelect) return;
|
|
1882
|
+
if (!mask.__label) return;
|
|
1922
1883
|
const coords = mask.getCoords ? mask.getCoords() : null;
|
|
1923
|
-
if (!coords || coords.length < 4)
|
|
1924
|
-
return;
|
|
1884
|
+
if (!coords || coords.length < 4) return;
|
|
1925
1885
|
const tl = coords[0];
|
|
1926
1886
|
const center = mask.getCenterPoint();
|
|
1927
1887
|
const vx = center.x - tl.x;
|
|
@@ -1954,12 +1914,9 @@ var ImageEditor = class {
|
|
|
1954
1914
|
* @private
|
|
1955
1915
|
*/
|
|
1956
1916
|
_showLabelForMask(mask) {
|
|
1957
|
-
if (!mask)
|
|
1958
|
-
|
|
1959
|
-
if (!this.
|
|
1960
|
-
return;
|
|
1961
|
-
if (!mask.__label)
|
|
1962
|
-
this._createLabelForMask(mask);
|
|
1917
|
+
if (!mask) return;
|
|
1918
|
+
if (!this.options.maskLabelOnSelect) return;
|
|
1919
|
+
if (!mask.__label) this._createLabelForMask(mask);
|
|
1963
1920
|
mask.__label.set({ visible: true });
|
|
1964
1921
|
this._syncMaskLabel(mask);
|
|
1965
1922
|
}
|
|
@@ -1979,6 +1936,7 @@ var ImageEditor = class {
|
|
|
1979
1936
|
try {
|
|
1980
1937
|
this.canvas.remove(mask.__label);
|
|
1981
1938
|
} catch (error) {
|
|
1939
|
+
void error;
|
|
1982
1940
|
}
|
|
1983
1941
|
delete mask.__label;
|
|
1984
1942
|
}
|
|
@@ -1991,8 +1949,7 @@ var ImageEditor = class {
|
|
|
1991
1949
|
mask.set({ stroke: "#ff0000", strokeWidth: 1 });
|
|
1992
1950
|
}
|
|
1993
1951
|
});
|
|
1994
|
-
if (selectedMask)
|
|
1995
|
-
this._showLabelForMask(selectedMask);
|
|
1952
|
+
if (selectedMask) this._showLabelForMask(selectedMask);
|
|
1996
1953
|
this._updateMaskListSelection(selectedMask);
|
|
1997
1954
|
this.canvas.renderAll();
|
|
1998
1955
|
this._updateUI();
|
|
@@ -2004,8 +1961,7 @@ var ImageEditor = class {
|
|
|
2004
1961
|
*/
|
|
2005
1962
|
_updateMaskList() {
|
|
2006
1963
|
const maskListElement = document.getElementById(this.elements.maskList);
|
|
2007
|
-
if (!maskListElement)
|
|
2008
|
-
return;
|
|
1964
|
+
if (!maskListElement) return;
|
|
2009
1965
|
maskListElement.innerHTML = "";
|
|
2010
1966
|
const masks = this.canvas.getObjects().filter((object) => object.maskId);
|
|
2011
1967
|
masks.forEach((mask) => {
|
|
@@ -2027,8 +1983,7 @@ var ImageEditor = class {
|
|
|
2027
1983
|
*/
|
|
2028
1984
|
_updateMaskListSelection(selectedMask) {
|
|
2029
1985
|
const maskListElement = document.getElementById(this.elements.maskList);
|
|
2030
|
-
if (!maskListElement)
|
|
2031
|
-
return;
|
|
1986
|
+
if (!maskListElement) return;
|
|
2032
1987
|
const maskItems = maskListElement.querySelectorAll(".mask-item");
|
|
2033
1988
|
maskItems.forEach((item) => {
|
|
2034
1989
|
const isSelected = !!selectedMask && item.textContent === selectedMask.maskName;
|
|
@@ -2046,11 +2001,9 @@ var ImageEditor = class {
|
|
|
2046
2001
|
* @public
|
|
2047
2002
|
*/
|
|
2048
2003
|
async mergeMasks() {
|
|
2049
|
-
if (!this.originalImage)
|
|
2050
|
-
return;
|
|
2004
|
+
if (!this.originalImage) return;
|
|
2051
2005
|
const masks = this.canvas.getObjects().filter((object) => object.maskId);
|
|
2052
|
-
if (!masks.length)
|
|
2053
|
-
return;
|
|
2006
|
+
if (!masks.length) return;
|
|
2054
2007
|
this.canvas.discardActiveObject();
|
|
2055
2008
|
this.canvas.renderAll();
|
|
2056
2009
|
try {
|
|
@@ -2082,8 +2035,7 @@ var ImageEditor = class {
|
|
|
2082
2035
|
* @public
|
|
2083
2036
|
*/
|
|
2084
2037
|
downloadImage(fileName = this.options.defaultDownloadFileName) {
|
|
2085
|
-
if (!this.originalImage)
|
|
2086
|
-
return;
|
|
2038
|
+
if (!this.originalImage) return;
|
|
2087
2039
|
const exportImageArea = this.options.exportImageAreaByDefault;
|
|
2088
2040
|
this.exportImageBase64({ exportImageArea, multiplier: this.options.exportMultiplier }).then((imageBase64) => {
|
|
2089
2041
|
const link = document.createElement("a");
|
|
@@ -2111,8 +2063,7 @@ var ImageEditor = class {
|
|
|
2111
2063
|
* @public
|
|
2112
2064
|
*/
|
|
2113
2065
|
async exportImageBase64(options = {}) {
|
|
2114
|
-
if (!this.originalImage)
|
|
2115
|
-
throw new Error("No image loaded");
|
|
2066
|
+
if (!this.originalImage) throw new Error("No image loaded");
|
|
2116
2067
|
const exportImageArea = typeof options.exportImageArea === "boolean" ? options.exportImageArea : this.options.exportImageAreaByDefault;
|
|
2117
2068
|
const multiplier = options.multiplier || this.options.exportMultiplier || 1;
|
|
2118
2069
|
const quality = this._normalizeQuality(options.quality ?? this.options.downsampleQuality);
|
|
@@ -2140,6 +2091,7 @@ var ImageEditor = class {
|
|
|
2140
2091
|
try {
|
|
2141
2092
|
backup.object.set({ visible: backup.visible });
|
|
2142
2093
|
} catch (error) {
|
|
2094
|
+
void error;
|
|
2143
2095
|
}
|
|
2144
2096
|
});
|
|
2145
2097
|
this.canvas.renderAll();
|
|
@@ -2187,6 +2139,7 @@ var ImageEditor = class {
|
|
|
2187
2139
|
});
|
|
2188
2140
|
backup.object.setCoords();
|
|
2189
2141
|
} catch (error) {
|
|
2142
|
+
void error;
|
|
2190
2143
|
}
|
|
2191
2144
|
});
|
|
2192
2145
|
this.canvas.renderAll();
|
|
@@ -2222,8 +2175,7 @@ var ImageEditor = class {
|
|
|
2222
2175
|
* const file = await this.exportImageFile({ mergeMask: false, fileType: 'png' });
|
|
2223
2176
|
*/
|
|
2224
2177
|
async exportImageFile(options = {}) {
|
|
2225
|
-
if (!this.originalImage)
|
|
2226
|
-
throw new Error("No image loaded");
|
|
2178
|
+
if (!this.originalImage) throw new Error("No image loaded");
|
|
2227
2179
|
const {
|
|
2228
2180
|
mergeMask = true,
|
|
2229
2181
|
fileType = "jpeg",
|
|
@@ -2287,8 +2239,7 @@ var ImageEditor = class {
|
|
|
2287
2239
|
}
|
|
2288
2240
|
async _restoreStateAfterCropFailure(beforeJson, message, error) {
|
|
2289
2241
|
this._reportError(message, error);
|
|
2290
|
-
if (this._cropRect && this.canvas)
|
|
2291
|
-
this._removeCropRect();
|
|
2242
|
+
if (this._cropRect && this.canvas) this._removeCropRect();
|
|
2292
2243
|
this._cropRect = null;
|
|
2293
2244
|
this._cropMode = false;
|
|
2294
2245
|
if (this.canvas && this._prevSelectionSetting !== void 0) {
|
|
@@ -2303,8 +2254,7 @@ var ImageEditor = class {
|
|
|
2303
2254
|
}
|
|
2304
2255
|
}
|
|
2305
2256
|
this._updateUI();
|
|
2306
|
-
if (this.canvas)
|
|
2307
|
-
this.canvas.renderAll();
|
|
2257
|
+
if (this.canvas) this.canvas.renderAll();
|
|
2308
2258
|
}
|
|
2309
2259
|
_restoreCropObjectState() {
|
|
2310
2260
|
if (Array.isArray(this._cropPrevEvented)) {
|
|
@@ -2316,14 +2266,14 @@ var ImageEditor = class {
|
|
|
2316
2266
|
visible: state.visible
|
|
2317
2267
|
});
|
|
2318
2268
|
} catch (error) {
|
|
2269
|
+
void error;
|
|
2319
2270
|
}
|
|
2320
2271
|
});
|
|
2321
2272
|
}
|
|
2322
2273
|
this._cropPrevEvented = null;
|
|
2323
2274
|
}
|
|
2324
2275
|
_removeCropRect() {
|
|
2325
|
-
if (!this._cropRect)
|
|
2326
|
-
return;
|
|
2276
|
+
if (!this._cropRect) return;
|
|
2327
2277
|
try {
|
|
2328
2278
|
if (this._cropHandlers && this._cropHandlers.length) {
|
|
2329
2279
|
this._cropHandlers.forEach((targetHandlers) => {
|
|
@@ -2333,10 +2283,12 @@ var ImageEditor = class {
|
|
|
2333
2283
|
});
|
|
2334
2284
|
}
|
|
2335
2285
|
} catch (error) {
|
|
2286
|
+
void error;
|
|
2336
2287
|
}
|
|
2337
2288
|
try {
|
|
2338
2289
|
this.canvas.remove(this._cropRect);
|
|
2339
2290
|
} catch (error) {
|
|
2291
|
+
void error;
|
|
2340
2292
|
}
|
|
2341
2293
|
this._cropRect = null;
|
|
2342
2294
|
this._cropHandlers = [];
|
|
@@ -2351,10 +2303,8 @@ var ImageEditor = class {
|
|
|
2351
2303
|
* @public
|
|
2352
2304
|
*/
|
|
2353
2305
|
enterCropMode() {
|
|
2354
|
-
if (!this.canvas || !this.originalImage || this._cropMode)
|
|
2355
|
-
|
|
2356
|
-
if (!this.isImageLoaded())
|
|
2357
|
-
return;
|
|
2306
|
+
if (!this.canvas || !this.originalImage || this._cropMode) return;
|
|
2307
|
+
if (!this.isImageLoaded()) return;
|
|
2358
2308
|
this._cropMode = true;
|
|
2359
2309
|
this._prevSelectionSetting = this.canvas.selection;
|
|
2360
2310
|
this.canvas.selection = false;
|
|
@@ -2406,10 +2356,10 @@ var ImageEditor = class {
|
|
|
2406
2356
|
evented: false,
|
|
2407
2357
|
selectable: false
|
|
2408
2358
|
};
|
|
2409
|
-
if (shouldHideMasks && (object.maskId || object.maskLabel))
|
|
2410
|
-
updates.visible = false;
|
|
2359
|
+
if (shouldHideMasks && (object.maskId || object.maskLabel)) updates.visible = false;
|
|
2411
2360
|
object.set(updates);
|
|
2412
2361
|
} catch (error) {
|
|
2362
|
+
void error;
|
|
2413
2363
|
}
|
|
2414
2364
|
}
|
|
2415
2365
|
});
|
|
@@ -2423,6 +2373,7 @@ var ImageEditor = class {
|
|
|
2423
2373
|
cropRect.setCoords();
|
|
2424
2374
|
this.canvas.requestRenderAll();
|
|
2425
2375
|
} catch (error) {
|
|
2376
|
+
void error;
|
|
2426
2377
|
}
|
|
2427
2378
|
};
|
|
2428
2379
|
cropRect.on("modified", handleCropRectModified);
|
|
@@ -2446,8 +2397,7 @@ var ImageEditor = class {
|
|
|
2446
2397
|
* @public
|
|
2447
2398
|
*/
|
|
2448
2399
|
cancelCrop() {
|
|
2449
|
-
if (!this.canvas || !this._cropMode)
|
|
2450
|
-
return;
|
|
2400
|
+
if (!this.canvas || !this._cropMode) return;
|
|
2451
2401
|
this._removeCropRect();
|
|
2452
2402
|
this._restoreCropObjectState();
|
|
2453
2403
|
this._cropMode = false;
|
|
@@ -2469,14 +2419,13 @@ var ImageEditor = class {
|
|
|
2469
2419
|
* @public
|
|
2470
2420
|
*/
|
|
2471
2421
|
async applyCrop() {
|
|
2472
|
-
if (!this.canvas || !this._cropMode || !this._cropRect)
|
|
2473
|
-
return;
|
|
2422
|
+
if (!this.canvas || !this._cropMode || !this._cropRect) return;
|
|
2474
2423
|
this._cropRect.setCoords();
|
|
2475
2424
|
const rectBounds = this._cropRect.getBoundingRect(true, true);
|
|
2476
|
-
const cropRegion = this._getClampedCanvasRegion(rectBounds);
|
|
2425
|
+
const cropRegion = this._getClampedCanvasRegion(rectBounds, { includePartialPixels: false });
|
|
2477
2426
|
const shouldPreserveMasks = !!(this.options.crop && this.options.crop.preserveMasksAfterCrop);
|
|
2478
2427
|
this._restoreCropObjectState();
|
|
2479
|
-
let beforeJson
|
|
2428
|
+
let beforeJson;
|
|
2480
2429
|
try {
|
|
2481
2430
|
beforeJson = this._serializeCanvasState();
|
|
2482
2431
|
} catch (error) {
|
|
@@ -2547,7 +2496,7 @@ var ImageEditor = class {
|
|
|
2547
2496
|
await this._restoreStateAfterCropFailure(beforeJson, "applyCrop: loadImage(croppedBase64) failed", error);
|
|
2548
2497
|
return;
|
|
2549
2498
|
}
|
|
2550
|
-
let afterJson
|
|
2499
|
+
let afterJson;
|
|
2551
2500
|
try {
|
|
2552
2501
|
afterJson = this._serializeCanvasState();
|
|
2553
2502
|
} catch (error) {
|
|
@@ -2570,8 +2519,7 @@ var ImageEditor = class {
|
|
|
2570
2519
|
*/
|
|
2571
2520
|
_updateInputs() {
|
|
2572
2521
|
const scaleInputElement = document.getElementById(this.elements.scaleRate);
|
|
2573
|
-
if (scaleInputElement)
|
|
2574
|
-
scaleInputElement.value = Math.round(this.currentScale * 100);
|
|
2522
|
+
if (scaleInputElement) scaleInputElement.value = Math.round(this.currentScale * 100);
|
|
2575
2523
|
}
|
|
2576
2524
|
/**
|
|
2577
2525
|
* Updates the enabled/disabled state of various UI controls (buttons)
|
|
@@ -2591,8 +2539,7 @@ var ImageEditor = class {
|
|
|
2591
2539
|
if (isInCropMode) {
|
|
2592
2540
|
for (const key of Object.keys(this.elements || {})) {
|
|
2593
2541
|
const element = document.getElementById(this.elements[key]);
|
|
2594
|
-
if (!element)
|
|
2595
|
-
continue;
|
|
2542
|
+
if (!element) continue;
|
|
2596
2543
|
if (key === "applyCropBtn" || key === "cancelCropBtn") {
|
|
2597
2544
|
this._setDisabled(key, false);
|
|
2598
2545
|
} else {
|
|
@@ -2628,8 +2575,7 @@ var ImageEditor = class {
|
|
|
2628
2575
|
*/
|
|
2629
2576
|
_setDisabled(key, disabled) {
|
|
2630
2577
|
const element = document.getElementById(this.elements[key]);
|
|
2631
|
-
if (!element)
|
|
2632
|
-
return;
|
|
2578
|
+
if (!element) return;
|
|
2633
2579
|
if ("disabled" in element) {
|
|
2634
2580
|
element.disabled = !!disabled;
|
|
2635
2581
|
return;
|
|
@@ -2643,10 +2589,8 @@ var ImageEditor = class {
|
|
|
2643
2589
|
}
|
|
2644
2590
|
}
|
|
2645
2591
|
_isElementDisabled(element) {
|
|
2646
|
-
if (!element)
|
|
2647
|
-
|
|
2648
|
-
if ("disabled" in element)
|
|
2649
|
-
return !!element.disabled;
|
|
2592
|
+
if (!element) return false;
|
|
2593
|
+
if ("disabled" in element) return !!element.disabled;
|
|
2650
2594
|
return element.getAttribute("aria-disabled") === "true";
|
|
2651
2595
|
}
|
|
2652
2596
|
/**
|
|
@@ -2654,8 +2598,7 @@ var ImageEditor = class {
|
|
|
2654
2598
|
* @private
|
|
2655
2599
|
*/
|
|
2656
2600
|
_updatePlaceholderStatus() {
|
|
2657
|
-
if (!this.options.showPlaceholder)
|
|
2658
|
-
return;
|
|
2601
|
+
if (!this.options.showPlaceholder) return;
|
|
2659
2602
|
this._setPlaceholderVisible(!this.originalImage);
|
|
2660
2603
|
}
|
|
2661
2604
|
/**
|
|
@@ -2665,17 +2608,23 @@ var ImageEditor = class {
|
|
|
2665
2608
|
* @private
|
|
2666
2609
|
*/
|
|
2667
2610
|
_setPlaceholderVisible(show) {
|
|
2668
|
-
if (!this.placeholderElement || !this.containerElement)
|
|
2669
|
-
|
|
2670
|
-
|
|
2671
|
-
|
|
2672
|
-
|
|
2673
|
-
|
|
2674
|
-
|
|
2675
|
-
|
|
2676
|
-
|
|
2677
|
-
|
|
2678
|
-
|
|
2611
|
+
if (!this.placeholderElement || !this.containerElement) return;
|
|
2612
|
+
this._setElementVisible(this.placeholderElement, show);
|
|
2613
|
+
this._setElementVisible(this.containerElement, !show);
|
|
2614
|
+
}
|
|
2615
|
+
/**
|
|
2616
|
+
* Updates element visibility.
|
|
2617
|
+
*
|
|
2618
|
+
* @param {HTMLElement} element - Element whose visibility should be updated.
|
|
2619
|
+
* @param {boolean} isVisible - If true, removes the hidden state.
|
|
2620
|
+
* @returns {void}
|
|
2621
|
+
* @private
|
|
2622
|
+
*/
|
|
2623
|
+
_setElementVisible(element, isVisible) {
|
|
2624
|
+
if (!element) return;
|
|
2625
|
+
element.hidden = !isVisible;
|
|
2626
|
+
element.setAttribute("aria-hidden", isVisible ? "false" : "true");
|
|
2627
|
+
if (isVisible && element.classList) element.classList.remove("d-none");
|
|
2679
2628
|
}
|
|
2680
2629
|
/**
|
|
2681
2630
|
* Cleans up and disposes of the canvas and related references.
|
|
@@ -2687,21 +2636,23 @@ var ImageEditor = class {
|
|
|
2687
2636
|
for (const key in this._handlersByElementKey || {}) {
|
|
2688
2637
|
const handlers = this._handlersByElementKey[key] || [];
|
|
2689
2638
|
const element = document.getElementById(this.elements[key]);
|
|
2690
|
-
if (!element)
|
|
2691
|
-
continue;
|
|
2639
|
+
if (!element) continue;
|
|
2692
2640
|
handlers.forEach((handlerRecord) => {
|
|
2693
2641
|
try {
|
|
2694
2642
|
element.removeEventListener(handlerRecord.eventName, handlerRecord.handler);
|
|
2695
2643
|
} catch (error) {
|
|
2644
|
+
void error;
|
|
2696
2645
|
}
|
|
2697
2646
|
});
|
|
2698
2647
|
}
|
|
2699
2648
|
} catch (error) {
|
|
2649
|
+
void error;
|
|
2700
2650
|
}
|
|
2701
2651
|
if (this._cropRect) {
|
|
2702
2652
|
try {
|
|
2703
2653
|
this.canvas.remove(this._cropRect);
|
|
2704
2654
|
} catch (error) {
|
|
2655
|
+
void error;
|
|
2705
2656
|
}
|
|
2706
2657
|
this._cropRect = null;
|
|
2707
2658
|
}
|
|
@@ -2709,12 +2660,14 @@ var ImageEditor = class {
|
|
|
2709
2660
|
try {
|
|
2710
2661
|
this.containerElement.style.overflow = this._containerOriginalOverflow;
|
|
2711
2662
|
} catch (error) {
|
|
2663
|
+
void error;
|
|
2712
2664
|
}
|
|
2713
2665
|
}
|
|
2714
2666
|
if (this.canvas) {
|
|
2715
2667
|
try {
|
|
2716
2668
|
this.canvas.dispose();
|
|
2717
2669
|
} catch (error) {
|
|
2670
|
+
void error;
|
|
2718
2671
|
}
|
|
2719
2672
|
this.canvas = null;
|
|
2720
2673
|
this.canvasElement = null;
|