@pooder/kit 1.0.0 → 2.0.0
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/CHANGELOG.md +11 -0
- package/dist/index.d.mts +29 -6
- package/dist/index.d.ts +29 -6
- package/dist/index.js +398 -58
- package/dist/index.mjs +428 -64
- package/package.json +2 -2
- package/src/background.ts +183 -172
- package/src/dieline.ts +580 -421
- package/src/film.ts +163 -156
- package/src/geometry.ts +251 -244
- package/src/hole.ts +493 -413
- package/src/image.ts +304 -147
- package/src/index.ts +8 -7
- package/src/mirror.ts +91 -0
- package/src/ruler.ts +255 -239
- package/src/white-ink.ts +329 -301
- package/tsconfig.json +13 -13
package/dist/index.js
CHANGED
|
@@ -35,6 +35,7 @@ __export(index_exports, {
|
|
|
35
35
|
FilmTool: () => FilmTool,
|
|
36
36
|
HoleTool: () => HoleTool,
|
|
37
37
|
ImageTool: () => ImageTool,
|
|
38
|
+
MirrorTool: () => MirrorTool,
|
|
38
39
|
RulerTool: () => RulerTool,
|
|
39
40
|
WhiteInkTool: () => WhiteInkTool
|
|
40
41
|
});
|
|
@@ -191,8 +192,7 @@ var BackgroundTool = class {
|
|
|
191
192
|
}
|
|
192
193
|
});
|
|
193
194
|
img.scaleToWidth(width);
|
|
194
|
-
if (img.getScaledHeight() < height)
|
|
195
|
-
img.scaleToHeight(height);
|
|
195
|
+
if (img.getScaledHeight() < height) img.scaleToHeight(height);
|
|
196
196
|
layer.add(img);
|
|
197
197
|
}
|
|
198
198
|
}
|
|
@@ -357,7 +357,8 @@ var DielineTool = class {
|
|
|
357
357
|
offset: 0,
|
|
358
358
|
style: "solid",
|
|
359
359
|
insideColor: "rgba(0,0,0,0)",
|
|
360
|
-
outsideColor: "#ffffff"
|
|
360
|
+
outsideColor: "#ffffff",
|
|
361
|
+
showBleedLines: true
|
|
361
362
|
};
|
|
362
363
|
this.schema = {
|
|
363
364
|
shape: {
|
|
@@ -372,6 +373,7 @@ var DielineTool = class {
|
|
|
372
373
|
// Complex object, simplified for now or need custom handler
|
|
373
374
|
borderLength: { type: "number", min: 0, max: 500, label: "Margin" },
|
|
374
375
|
offset: { type: "number", min: -100, max: 100, label: "Bleed Offset" },
|
|
376
|
+
showBleedLines: { type: "boolean", label: "Show Bleed Lines" },
|
|
375
377
|
style: {
|
|
376
378
|
type: "select",
|
|
377
379
|
options: ["solid", "dashed"],
|
|
@@ -391,7 +393,8 @@ var DielineTool = class {
|
|
|
391
393
|
offset: 0,
|
|
392
394
|
style: "solid",
|
|
393
395
|
insideColor: "rgba(0,0,0,0)",
|
|
394
|
-
outsideColor: "#ffffff"
|
|
396
|
+
outsideColor: "#ffffff",
|
|
397
|
+
showBleedLines: true
|
|
395
398
|
};
|
|
396
399
|
this.updateDieline(editor);
|
|
397
400
|
return true;
|
|
@@ -405,7 +408,8 @@ var DielineTool = class {
|
|
|
405
408
|
},
|
|
406
409
|
setDimensions: {
|
|
407
410
|
execute: (editor, width, height) => {
|
|
408
|
-
if (this.options.width === width && this.options.height === height)
|
|
411
|
+
if (this.options.width === width && this.options.height === height)
|
|
412
|
+
return true;
|
|
409
413
|
this.options.width = width;
|
|
410
414
|
this.options.height = height;
|
|
411
415
|
this.updateDieline(editor);
|
|
@@ -460,6 +464,94 @@ var DielineTool = class {
|
|
|
460
464
|
required: true
|
|
461
465
|
}
|
|
462
466
|
}
|
|
467
|
+
},
|
|
468
|
+
exportCutImage: {
|
|
469
|
+
execute: (editor) => {
|
|
470
|
+
var _a, _b, _c, _d;
|
|
471
|
+
const { shape, width, height, radius, position } = this.options;
|
|
472
|
+
const canvasW = editor.canvas.width || 800;
|
|
473
|
+
const canvasH = editor.canvas.height || 600;
|
|
474
|
+
const cx = (_a = position == null ? void 0 : position.x) != null ? _a : canvasW / 2;
|
|
475
|
+
const cy = (_b = position == null ? void 0 : position.y) != null ? _b : canvasH / 2;
|
|
476
|
+
const holeTool = editor.getExtension("HoleTool");
|
|
477
|
+
const holes = holeTool ? holeTool.options.holes || [] : [];
|
|
478
|
+
const innerRadius = holeTool ? holeTool.options.innerRadius || 15 : 15;
|
|
479
|
+
const outerRadius = holeTool ? holeTool.options.outerRadius || 25 : 25;
|
|
480
|
+
const holeData = holes.map((h) => ({
|
|
481
|
+
x: h.x,
|
|
482
|
+
y: h.y,
|
|
483
|
+
innerRadius,
|
|
484
|
+
outerRadius
|
|
485
|
+
}));
|
|
486
|
+
const pathData = generateDielinePath({
|
|
487
|
+
shape,
|
|
488
|
+
width,
|
|
489
|
+
height,
|
|
490
|
+
radius,
|
|
491
|
+
x: cx,
|
|
492
|
+
y: cy,
|
|
493
|
+
holes: holeData
|
|
494
|
+
});
|
|
495
|
+
const clipPath = new import_core2.Path(pathData, {
|
|
496
|
+
left: 0,
|
|
497
|
+
top: 0,
|
|
498
|
+
originX: "left",
|
|
499
|
+
originY: "top",
|
|
500
|
+
absolutePositioned: true
|
|
501
|
+
});
|
|
502
|
+
const layer = this.getLayer(editor, "dieline-overlay");
|
|
503
|
+
const wasVisible = (_c = layer == null ? void 0 : layer.visible) != null ? _c : true;
|
|
504
|
+
if (layer) layer.visible = false;
|
|
505
|
+
const holeMarkers = editor.canvas.getObjects().filter((o) => {
|
|
506
|
+
var _a2;
|
|
507
|
+
return ((_a2 = o.data) == null ? void 0 : _a2.type) === "hole-marker";
|
|
508
|
+
});
|
|
509
|
+
holeMarkers.forEach((o) => o.visible = false);
|
|
510
|
+
const rulerLayer = editor.canvas.getObjects().find((obj) => {
|
|
511
|
+
var _a2;
|
|
512
|
+
return ((_a2 = obj.data) == null ? void 0 : _a2.id) === "ruler-overlay";
|
|
513
|
+
});
|
|
514
|
+
const rulerWasVisible = (_d = rulerLayer == null ? void 0 : rulerLayer.visible) != null ? _d : true;
|
|
515
|
+
if (rulerLayer) rulerLayer.visible = false;
|
|
516
|
+
const originalClip = editor.canvas.clipPath;
|
|
517
|
+
editor.canvas.clipPath = clipPath;
|
|
518
|
+
const bbox = clipPath.getBoundingRect();
|
|
519
|
+
const holeDataRelative = holes.map((h) => ({
|
|
520
|
+
x: h.x - bbox.left,
|
|
521
|
+
y: h.y - bbox.top,
|
|
522
|
+
innerRadius,
|
|
523
|
+
outerRadius
|
|
524
|
+
}));
|
|
525
|
+
const clipPathCorrected = new import_core2.Path(pathData, {
|
|
526
|
+
absolutePositioned: true,
|
|
527
|
+
left: 0,
|
|
528
|
+
top: 0
|
|
529
|
+
});
|
|
530
|
+
const tempPath = new import_core2.Path(pathData);
|
|
531
|
+
const tempBounds = tempPath.getBoundingRect();
|
|
532
|
+
clipPathCorrected.set({
|
|
533
|
+
left: tempBounds.left,
|
|
534
|
+
top: tempBounds.top,
|
|
535
|
+
originX: "left",
|
|
536
|
+
originY: "top"
|
|
537
|
+
});
|
|
538
|
+
editor.canvas.clipPath = clipPathCorrected;
|
|
539
|
+
const exportBbox = clipPathCorrected.getBoundingRect();
|
|
540
|
+
const dataURL = editor.canvas.toDataURL({
|
|
541
|
+
format: "png",
|
|
542
|
+
multiplier: 2,
|
|
543
|
+
left: exportBbox.left,
|
|
544
|
+
top: exportBbox.top,
|
|
545
|
+
width: exportBbox.width,
|
|
546
|
+
height: exportBbox.height
|
|
547
|
+
});
|
|
548
|
+
editor.canvas.clipPath = originalClip;
|
|
549
|
+
if (layer) layer.visible = wasVisible;
|
|
550
|
+
if (rulerLayer) rulerLayer.visible = rulerWasVisible;
|
|
551
|
+
holeMarkers.forEach((o) => o.visible = true);
|
|
552
|
+
editor.canvas.requestRenderAll();
|
|
553
|
+
return dataURL;
|
|
554
|
+
}
|
|
463
555
|
}
|
|
464
556
|
};
|
|
465
557
|
}
|
|
@@ -526,7 +618,17 @@ var DielineTool = class {
|
|
|
526
618
|
}
|
|
527
619
|
updateDieline(editor) {
|
|
528
620
|
var _a, _b;
|
|
529
|
-
const {
|
|
621
|
+
const {
|
|
622
|
+
shape,
|
|
623
|
+
radius,
|
|
624
|
+
offset,
|
|
625
|
+
style,
|
|
626
|
+
insideColor,
|
|
627
|
+
outsideColor,
|
|
628
|
+
position,
|
|
629
|
+
borderLength,
|
|
630
|
+
showBleedLines
|
|
631
|
+
} = this.options;
|
|
530
632
|
let { width, height } = this.options;
|
|
531
633
|
const canvasW = editor.canvas.width || 800;
|
|
532
634
|
const canvasH = editor.canvas.height || 600;
|
|
@@ -540,6 +642,9 @@ var DielineTool = class {
|
|
|
540
642
|
if (!layer) return;
|
|
541
643
|
layer.remove(...layer.getObjects());
|
|
542
644
|
const holeTool = editor.getExtension("HoleTool");
|
|
645
|
+
if (holeTool && typeof holeTool.enforceConstraints === "function") {
|
|
646
|
+
holeTool.enforceConstraints(editor);
|
|
647
|
+
}
|
|
543
648
|
const holes = holeTool ? holeTool.options.holes || [] : [];
|
|
544
649
|
const innerRadius = holeTool ? holeTool.options.innerRadius || 15 : 15;
|
|
545
650
|
const outerRadius = holeTool ? holeTool.options.outerRadius || 25 : 25;
|
|
@@ -596,27 +701,32 @@ var DielineTool = class {
|
|
|
596
701
|
layer.add(insideObj);
|
|
597
702
|
}
|
|
598
703
|
if (offset !== 0) {
|
|
599
|
-
const bleedPathData = generateBleedZonePath(
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
704
|
+
const bleedPathData = generateBleedZonePath(
|
|
705
|
+
{
|
|
706
|
+
shape,
|
|
707
|
+
width,
|
|
708
|
+
height,
|
|
709
|
+
radius,
|
|
710
|
+
x: cx,
|
|
711
|
+
y: cy,
|
|
712
|
+
holes: holeData
|
|
713
|
+
},
|
|
714
|
+
offset
|
|
715
|
+
);
|
|
716
|
+
if (showBleedLines !== false) {
|
|
717
|
+
const pattern = this.createHatchPattern("red");
|
|
718
|
+
if (pattern) {
|
|
719
|
+
const bleedObj = new import_core2.Path(bleedPathData, {
|
|
720
|
+
fill: pattern,
|
|
721
|
+
stroke: null,
|
|
722
|
+
selectable: false,
|
|
723
|
+
evented: false,
|
|
724
|
+
objectCaching: false,
|
|
725
|
+
originX: "left",
|
|
726
|
+
originY: "top"
|
|
727
|
+
});
|
|
728
|
+
layer.add(bleedObj);
|
|
729
|
+
}
|
|
620
730
|
}
|
|
621
731
|
const offsetPathData = generateDielinePath({
|
|
622
732
|
shape,
|
|
@@ -712,7 +822,8 @@ var FilmTool = class {
|
|
|
712
822
|
this.commands = {
|
|
713
823
|
setFilmImage: {
|
|
714
824
|
execute: (editor, url, opacity) => {
|
|
715
|
-
if (this.options.url === url && this.options.opacity === opacity)
|
|
825
|
+
if (this.options.url === url && this.options.opacity === opacity)
|
|
826
|
+
return true;
|
|
716
827
|
this.options.url = url;
|
|
717
828
|
this.options.opacity = opacity;
|
|
718
829
|
this.updateFilm(editor, this.options);
|
|
@@ -803,8 +914,7 @@ var FilmTool = class {
|
|
|
803
914
|
} else {
|
|
804
915
|
img = await import_core3.Image.fromURL(url, { crossOrigin: "anonymous" });
|
|
805
916
|
img.scaleToWidth(width);
|
|
806
|
-
if (img.getScaledHeight() < height)
|
|
807
|
-
img.scaleToHeight(height);
|
|
917
|
+
if (img.getScaledHeight() < height) img.scaleToHeight(height);
|
|
808
918
|
img.set({
|
|
809
919
|
originX: "left",
|
|
810
920
|
originY: "top",
|
|
@@ -833,7 +943,8 @@ var HoleTool = class {
|
|
|
833
943
|
innerRadius: 15,
|
|
834
944
|
outerRadius: 25,
|
|
835
945
|
style: "solid",
|
|
836
|
-
holes: []
|
|
946
|
+
holes: [],
|
|
947
|
+
constraintTarget: "bleed"
|
|
837
948
|
};
|
|
838
949
|
this.schema = {
|
|
839
950
|
innerRadius: {
|
|
@@ -853,6 +964,11 @@ var HoleTool = class {
|
|
|
853
964
|
options: ["solid", "dashed"],
|
|
854
965
|
label: "Line Style"
|
|
855
966
|
},
|
|
967
|
+
constraintTarget: {
|
|
968
|
+
type: "select",
|
|
969
|
+
options: ["original", "bleed"],
|
|
970
|
+
label: "Constraint Target"
|
|
971
|
+
},
|
|
856
972
|
holes: {
|
|
857
973
|
type: "json",
|
|
858
974
|
label: "Holes"
|
|
@@ -867,7 +983,10 @@ var HoleTool = class {
|
|
|
867
983
|
const g = this.getDielineGeometry(editor);
|
|
868
984
|
if (g) {
|
|
869
985
|
const topCenter = { x: g.x, y: g.y - g.height / 2 };
|
|
870
|
-
defaultPos = getNearestPointOnDieline(topCenter, {
|
|
986
|
+
defaultPos = getNearestPointOnDieline(topCenter, {
|
|
987
|
+
...g,
|
|
988
|
+
holes: []
|
|
989
|
+
});
|
|
871
990
|
}
|
|
872
991
|
this.options = {
|
|
873
992
|
innerRadius: 15,
|
|
@@ -934,7 +1053,7 @@ var HoleTool = class {
|
|
|
934
1053
|
if (!dielineTool) return null;
|
|
935
1054
|
const geometry = dielineTool.getGeometry(editor);
|
|
936
1055
|
if (!geometry) return null;
|
|
937
|
-
const offset = dielineTool.options.offset || 0;
|
|
1056
|
+
const offset = this.options.constraintTarget === "original" ? 0 : dielineTool.options.offset || 0;
|
|
938
1057
|
return {
|
|
939
1058
|
...geometry,
|
|
940
1059
|
width: Math.max(0, geometry.width + offset * 2),
|
|
@@ -942,6 +1061,39 @@ var HoleTool = class {
|
|
|
942
1061
|
radius: Math.max(0, geometry.radius + offset)
|
|
943
1062
|
};
|
|
944
1063
|
}
|
|
1064
|
+
enforceConstraints(editor) {
|
|
1065
|
+
const geometry = this.getDielineGeometry(editor);
|
|
1066
|
+
if (!geometry) return;
|
|
1067
|
+
const objects = editor.canvas.getObjects().filter((obj) => {
|
|
1068
|
+
var _a;
|
|
1069
|
+
return ((_a = obj.data) == null ? void 0 : _a.type) === "hole-marker";
|
|
1070
|
+
});
|
|
1071
|
+
let changed = false;
|
|
1072
|
+
objects.sort(
|
|
1073
|
+
(a, b) => {
|
|
1074
|
+
var _a, _b, _c, _d;
|
|
1075
|
+
return ((_b = (_a = a.data) == null ? void 0 : _a.index) != null ? _b : 0) - ((_d = (_c = b.data) == null ? void 0 : _c.index) != null ? _d : 0);
|
|
1076
|
+
}
|
|
1077
|
+
);
|
|
1078
|
+
const newHoles = [];
|
|
1079
|
+
objects.forEach((obj) => {
|
|
1080
|
+
const currentPos = new import_core4.Point(obj.left, obj.top);
|
|
1081
|
+
const newPos = this.calculateConstrainedPosition(currentPos, geometry);
|
|
1082
|
+
if (currentPos.distanceFrom(newPos) > 0.1) {
|
|
1083
|
+
obj.set({
|
|
1084
|
+
left: newPos.x,
|
|
1085
|
+
top: newPos.y
|
|
1086
|
+
});
|
|
1087
|
+
obj.setCoords();
|
|
1088
|
+
changed = true;
|
|
1089
|
+
}
|
|
1090
|
+
newHoles.push({ x: obj.left, y: obj.top });
|
|
1091
|
+
});
|
|
1092
|
+
if (changed) {
|
|
1093
|
+
this.options.holes = newHoles;
|
|
1094
|
+
editor.canvas.requestRenderAll();
|
|
1095
|
+
}
|
|
1096
|
+
}
|
|
945
1097
|
setup(editor) {
|
|
946
1098
|
if (!this.handleMoving) {
|
|
947
1099
|
this.handleMoving = (e) => {
|
|
@@ -974,7 +1126,10 @@ var HoleTool = class {
|
|
|
974
1126
|
const g = this.getDielineGeometry(editor);
|
|
975
1127
|
if (g) {
|
|
976
1128
|
const topCenter = { x: g.x, y: g.y - g.height / 2 };
|
|
977
|
-
const snapped = getNearestPointOnDieline(topCenter, {
|
|
1129
|
+
const snapped = getNearestPointOnDieline(topCenter, {
|
|
1130
|
+
...g,
|
|
1131
|
+
holes: []
|
|
1132
|
+
});
|
|
978
1133
|
defaultPos = snapped;
|
|
979
1134
|
}
|
|
980
1135
|
opts.holes = [defaultPos];
|
|
@@ -1003,6 +1158,12 @@ var HoleTool = class {
|
|
|
1003
1158
|
editor.canvas.requestRenderAll();
|
|
1004
1159
|
}
|
|
1005
1160
|
onUpdate(editor, state) {
|
|
1161
|
+
this.enforceConstraints(editor);
|
|
1162
|
+
this.redraw(editor);
|
|
1163
|
+
const dielineTool = editor.getExtension("DielineTool");
|
|
1164
|
+
if (dielineTool && dielineTool.updateDieline) {
|
|
1165
|
+
dielineTool.updateDieline(editor);
|
|
1166
|
+
}
|
|
1006
1167
|
}
|
|
1007
1168
|
syncHolesFromCanvas(editor) {
|
|
1008
1169
|
const objects = editor.canvas.getObjects().filter((obj) => {
|
|
@@ -1091,7 +1252,10 @@ var HoleTool = class {
|
|
|
1091
1252
|
holes: []
|
|
1092
1253
|
// We don't need holes for boundary calculation
|
|
1093
1254
|
};
|
|
1094
|
-
const nearest = getNearestPointOnDieline(
|
|
1255
|
+
const nearest = getNearestPointOnDieline(
|
|
1256
|
+
{ x: p.x, y: p.y },
|
|
1257
|
+
options
|
|
1258
|
+
);
|
|
1095
1259
|
const nearestP = new import_core4.Point(nearest.x, nearest.y);
|
|
1096
1260
|
const dist = p.distanceFrom(nearestP);
|
|
1097
1261
|
const v = p.subtract(nearestP);
|
|
@@ -1122,6 +1286,7 @@ var import_core5 = require("@pooder/core");
|
|
|
1122
1286
|
var ImageTool = class {
|
|
1123
1287
|
constructor() {
|
|
1124
1288
|
this.name = "ImageTool";
|
|
1289
|
+
this._loadingUrl = null;
|
|
1125
1290
|
this.options = {
|
|
1126
1291
|
url: "",
|
|
1127
1292
|
opacity: 1
|
|
@@ -1137,14 +1302,44 @@ var ImageTool = class {
|
|
|
1137
1302
|
max: 1,
|
|
1138
1303
|
step: 0.1,
|
|
1139
1304
|
label: "Opacity"
|
|
1305
|
+
},
|
|
1306
|
+
width: {
|
|
1307
|
+
type: "number",
|
|
1308
|
+
label: "Width",
|
|
1309
|
+
min: 0,
|
|
1310
|
+
max: 5e3
|
|
1311
|
+
},
|
|
1312
|
+
height: {
|
|
1313
|
+
type: "number",
|
|
1314
|
+
label: "Height",
|
|
1315
|
+
min: 0,
|
|
1316
|
+
max: 5e3
|
|
1317
|
+
},
|
|
1318
|
+
angle: {
|
|
1319
|
+
type: "number",
|
|
1320
|
+
label: "Rotation",
|
|
1321
|
+
min: 0,
|
|
1322
|
+
max: 360
|
|
1323
|
+
},
|
|
1324
|
+
left: {
|
|
1325
|
+
type: "number",
|
|
1326
|
+
label: "Left",
|
|
1327
|
+
min: 0,
|
|
1328
|
+
max: 1e3
|
|
1329
|
+
},
|
|
1330
|
+
top: {
|
|
1331
|
+
type: "number",
|
|
1332
|
+
label: "Top",
|
|
1333
|
+
min: 0,
|
|
1334
|
+
max: 1e3
|
|
1140
1335
|
}
|
|
1141
1336
|
};
|
|
1142
1337
|
this.commands = {
|
|
1143
1338
|
setUserImage: {
|
|
1144
|
-
execute: (editor, url, opacity) => {
|
|
1145
|
-
if (this.options.url === url && this.options.opacity === opacity
|
|
1146
|
-
|
|
1147
|
-
this.options
|
|
1339
|
+
execute: (editor, url, opacity, width, height, angle, left, top) => {
|
|
1340
|
+
if (this.options.url === url && this.options.opacity === opacity && this.options.width === width && this.options.height === height && this.options.angle === angle && this.options.left === left && this.options.top === top)
|
|
1341
|
+
return true;
|
|
1342
|
+
this.options = { url, opacity, width, height, angle, left, top };
|
|
1148
1343
|
this.updateImage(editor, this.options);
|
|
1149
1344
|
return true;
|
|
1150
1345
|
},
|
|
@@ -1160,7 +1355,12 @@ var ImageTool = class {
|
|
|
1160
1355
|
min: 0,
|
|
1161
1356
|
max: 1,
|
|
1162
1357
|
required: true
|
|
1163
|
-
}
|
|
1358
|
+
},
|
|
1359
|
+
width: { type: "number", label: "Width" },
|
|
1360
|
+
height: { type: "number", label: "Height" },
|
|
1361
|
+
angle: { type: "number", label: "Angle" },
|
|
1362
|
+
left: { type: "number", label: "Left" },
|
|
1363
|
+
top: { type: "number", label: "Top" }
|
|
1164
1364
|
}
|
|
1165
1365
|
}
|
|
1166
1366
|
};
|
|
@@ -1205,43 +1405,101 @@ var ImageTool = class {
|
|
|
1205
1405
|
}
|
|
1206
1406
|
updateImage(editor, opts) {
|
|
1207
1407
|
var _a, _b;
|
|
1208
|
-
let { url, opacity } = opts;
|
|
1408
|
+
let { url, opacity, width, height, angle, left, top } = opts;
|
|
1209
1409
|
const layer = editor.getLayer("user");
|
|
1210
1410
|
if (!layer) {
|
|
1211
1411
|
console.warn("[ImageTool] User layer not found");
|
|
1212
1412
|
return;
|
|
1213
1413
|
}
|
|
1214
1414
|
const userImage = editor.getObject("user-image", "user");
|
|
1415
|
+
if (this._loadingUrl === url) return;
|
|
1215
1416
|
if (userImage) {
|
|
1216
1417
|
const currentSrc = ((_a = userImage.getSrc) == null ? void 0 : _a.call(userImage)) || ((_b = userImage._element) == null ? void 0 : _b.src);
|
|
1217
1418
|
if (currentSrc !== url) {
|
|
1218
|
-
this.loadImage(editor, layer,
|
|
1419
|
+
this.loadImage(editor, layer, opts);
|
|
1219
1420
|
} else {
|
|
1220
|
-
|
|
1221
|
-
|
|
1421
|
+
const updates = {};
|
|
1422
|
+
const centerX = editor.state.width / 2;
|
|
1423
|
+
const centerY = editor.state.height / 2;
|
|
1424
|
+
if (userImage.opacity !== opacity) updates.opacity = opacity;
|
|
1425
|
+
if (angle !== void 0 && userImage.angle !== angle)
|
|
1426
|
+
updates.angle = angle;
|
|
1427
|
+
if (left !== void 0) {
|
|
1428
|
+
const localLeft = left - centerX;
|
|
1429
|
+
if (Math.abs(userImage.left - localLeft) > 1)
|
|
1430
|
+
updates.left = localLeft;
|
|
1431
|
+
}
|
|
1432
|
+
if (top !== void 0) {
|
|
1433
|
+
const localTop = top - centerY;
|
|
1434
|
+
if (Math.abs(userImage.top - localTop) > 1) updates.top = localTop;
|
|
1435
|
+
}
|
|
1436
|
+
if (width !== void 0 && userImage.width)
|
|
1437
|
+
updates.scaleX = width / userImage.width;
|
|
1438
|
+
if (height !== void 0 && userImage.height)
|
|
1439
|
+
updates.scaleY = height / userImage.height;
|
|
1440
|
+
if (Object.keys(updates).length > 0) {
|
|
1441
|
+
userImage.set(updates);
|
|
1222
1442
|
editor.canvas.requestRenderAll();
|
|
1223
1443
|
}
|
|
1224
1444
|
}
|
|
1225
1445
|
} else {
|
|
1226
|
-
this.loadImage(editor, layer,
|
|
1446
|
+
this.loadImage(editor, layer, opts);
|
|
1227
1447
|
}
|
|
1228
1448
|
}
|
|
1229
|
-
loadImage(editor, layer,
|
|
1449
|
+
loadImage(editor, layer, opts) {
|
|
1450
|
+
const { url } = opts;
|
|
1451
|
+
this._loadingUrl = url;
|
|
1230
1452
|
import_core5.Image.fromURL(url).then((image) => {
|
|
1231
|
-
if (
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1453
|
+
if (this._loadingUrl !== url) return;
|
|
1454
|
+
this._loadingUrl = null;
|
|
1455
|
+
const currentOpts = this.options;
|
|
1456
|
+
const { opacity, width, height, angle, left, top } = currentOpts;
|
|
1457
|
+
const existingImage = editor.getObject("user-image", "user");
|
|
1458
|
+
if (existingImage) {
|
|
1459
|
+
const defaultLeft = existingImage.left;
|
|
1460
|
+
const defaultTop = existingImage.top;
|
|
1461
|
+
const defaultAngle = existingImage.angle;
|
|
1462
|
+
const defaultScaleX = existingImage.scaleX;
|
|
1463
|
+
const defaultScaleY = existingImage.scaleY;
|
|
1464
|
+
image.set({
|
|
1465
|
+
left: left !== void 0 ? left : defaultLeft,
|
|
1466
|
+
top: top !== void 0 ? top : defaultTop,
|
|
1467
|
+
angle: angle !== void 0 ? angle : defaultAngle,
|
|
1468
|
+
scaleX: width !== void 0 && image.width ? width / image.width : defaultScaleX,
|
|
1469
|
+
scaleY: height !== void 0 && image.height ? height / image.height : defaultScaleY
|
|
1470
|
+
});
|
|
1471
|
+
layer.remove(existingImage);
|
|
1472
|
+
} else {
|
|
1473
|
+
if (width !== void 0 && image.width)
|
|
1474
|
+
image.scaleX = width / image.width;
|
|
1475
|
+
if (height !== void 0 && image.height)
|
|
1476
|
+
image.scaleY = height / image.height;
|
|
1477
|
+
if (angle !== void 0) image.angle = angle;
|
|
1478
|
+
if (left !== void 0) image.left = left;
|
|
1479
|
+
if (top !== void 0) image.top = top;
|
|
1235
1480
|
}
|
|
1236
1481
|
image.set({
|
|
1237
|
-
opacity,
|
|
1482
|
+
opacity: opacity !== void 0 ? opacity : 1,
|
|
1238
1483
|
data: {
|
|
1239
1484
|
id: "user-image"
|
|
1240
1485
|
}
|
|
1241
1486
|
});
|
|
1242
1487
|
layer.add(image);
|
|
1488
|
+
image.on("modified", (e) => {
|
|
1489
|
+
const matrix = image.calcTransformMatrix();
|
|
1490
|
+
const globalPoint = import_core5.util.transformPoint(new import_core5.Point(0, 0), matrix);
|
|
1491
|
+
this.options.left = globalPoint.x;
|
|
1492
|
+
this.options.top = globalPoint.y;
|
|
1493
|
+
this.options.angle = e.target.angle;
|
|
1494
|
+
if (image.width)
|
|
1495
|
+
this.options.width = e.target.width * e.target.scaleX;
|
|
1496
|
+
if (image.height)
|
|
1497
|
+
this.options.height = e.target.height * e.target.scaleY;
|
|
1498
|
+
editor.emit("update");
|
|
1499
|
+
});
|
|
1243
1500
|
editor.canvas.requestRenderAll();
|
|
1244
1501
|
}).catch((err) => {
|
|
1502
|
+
if (this._loadingUrl === url) this._loadingUrl = null;
|
|
1245
1503
|
console.error("Failed to load image", url, err);
|
|
1246
1504
|
});
|
|
1247
1505
|
}
|
|
@@ -1265,7 +1523,8 @@ var WhiteInkTool = class {
|
|
|
1265
1523
|
this.commands = {
|
|
1266
1524
|
setWhiteInkImage: {
|
|
1267
1525
|
execute: (editor, customMask, opacity, enableClip = true) => {
|
|
1268
|
-
if (this.options.customMask === customMask && this.options.opacity === opacity && this.options.enableClip === enableClip)
|
|
1526
|
+
if (this.options.customMask === customMask && this.options.opacity === opacity && this.options.enableClip === enableClip)
|
|
1527
|
+
return true;
|
|
1269
1528
|
this.options.customMask = customMask;
|
|
1270
1529
|
this.options.opacity = opacity;
|
|
1271
1530
|
this.options.enableClip = enableClip;
|
|
@@ -1386,7 +1645,14 @@ var WhiteInkTool = class {
|
|
|
1386
1645
|
if (whiteInk) {
|
|
1387
1646
|
const currentSrc = ((_a = whiteInk.getSrc) == null ? void 0 : _a.call(whiteInk)) || ((_b = whiteInk._element) == null ? void 0 : _b.src);
|
|
1388
1647
|
if (currentSrc !== customMask) {
|
|
1389
|
-
this.loadWhiteInk(
|
|
1648
|
+
this.loadWhiteInk(
|
|
1649
|
+
editor,
|
|
1650
|
+
layer,
|
|
1651
|
+
customMask,
|
|
1652
|
+
opacity,
|
|
1653
|
+
enableClip,
|
|
1654
|
+
whiteInk
|
|
1655
|
+
);
|
|
1390
1656
|
} else {
|
|
1391
1657
|
if (whiteInk.opacity !== opacity) {
|
|
1392
1658
|
whiteInk.set({ opacity });
|
|
@@ -1415,10 +1681,12 @@ var WhiteInkTool = class {
|
|
|
1415
1681
|
if (oldImage) {
|
|
1416
1682
|
layer.remove(oldImage);
|
|
1417
1683
|
}
|
|
1418
|
-
(_a = image.filters) == null ? void 0 : _a.push(
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1684
|
+
(_a = image.filters) == null ? void 0 : _a.push(
|
|
1685
|
+
new import_core6.filters.BlendColor({
|
|
1686
|
+
color: "#FFFFFF",
|
|
1687
|
+
mode: "add"
|
|
1688
|
+
})
|
|
1689
|
+
);
|
|
1422
1690
|
image.applyFilters();
|
|
1423
1691
|
image.set({
|
|
1424
1692
|
opacity,
|
|
@@ -1530,7 +1798,8 @@ var RulerTool = class {
|
|
|
1530
1798
|
setTheme: {
|
|
1531
1799
|
execute: (editor, theme) => {
|
|
1532
1800
|
const newOptions = { ...this.options, ...theme };
|
|
1533
|
-
if (JSON.stringify(newOptions) === JSON.stringify(this.options))
|
|
1801
|
+
if (JSON.stringify(newOptions) === JSON.stringify(this.options))
|
|
1802
|
+
return true;
|
|
1534
1803
|
this.options = newOptions;
|
|
1535
1804
|
this.updateRuler(editor);
|
|
1536
1805
|
return true;
|
|
@@ -1684,6 +1953,76 @@ var RulerTool = class {
|
|
|
1684
1953
|
editor.canvas.requestRenderAll();
|
|
1685
1954
|
}
|
|
1686
1955
|
};
|
|
1956
|
+
|
|
1957
|
+
// src/mirror.ts
|
|
1958
|
+
var MirrorTool = class {
|
|
1959
|
+
constructor() {
|
|
1960
|
+
this.name = "MirrorTool";
|
|
1961
|
+
this.options = {
|
|
1962
|
+
enabled: false
|
|
1963
|
+
};
|
|
1964
|
+
this.schema = {
|
|
1965
|
+
enabled: {
|
|
1966
|
+
type: "boolean",
|
|
1967
|
+
label: "Mirror View"
|
|
1968
|
+
}
|
|
1969
|
+
};
|
|
1970
|
+
this.commands = {
|
|
1971
|
+
toggleMirror: {
|
|
1972
|
+
execute: (editor) => {
|
|
1973
|
+
this.options.enabled = !this.options.enabled;
|
|
1974
|
+
this.applyMirror(editor, this.options.enabled);
|
|
1975
|
+
return true;
|
|
1976
|
+
}
|
|
1977
|
+
},
|
|
1978
|
+
setMirror: {
|
|
1979
|
+
execute: (editor, enabled) => {
|
|
1980
|
+
if (this.options.enabled === enabled) return true;
|
|
1981
|
+
this.options.enabled = enabled;
|
|
1982
|
+
this.applyMirror(editor, enabled);
|
|
1983
|
+
return true;
|
|
1984
|
+
},
|
|
1985
|
+
schema: {
|
|
1986
|
+
enabled: {
|
|
1987
|
+
type: "boolean",
|
|
1988
|
+
label: "Enabled",
|
|
1989
|
+
required: true
|
|
1990
|
+
}
|
|
1991
|
+
}
|
|
1992
|
+
}
|
|
1993
|
+
};
|
|
1994
|
+
}
|
|
1995
|
+
onMount(editor) {
|
|
1996
|
+
if (this.options.enabled) {
|
|
1997
|
+
this.applyMirror(editor, true);
|
|
1998
|
+
}
|
|
1999
|
+
}
|
|
2000
|
+
onUpdate(editor) {
|
|
2001
|
+
this.applyMirror(editor, this.options.enabled);
|
|
2002
|
+
}
|
|
2003
|
+
onUnmount(editor) {
|
|
2004
|
+
this.applyMirror(editor, false);
|
|
2005
|
+
}
|
|
2006
|
+
applyMirror(editor, enabled) {
|
|
2007
|
+
const canvas = editor.canvas;
|
|
2008
|
+
if (!canvas) return;
|
|
2009
|
+
const width = canvas.width || 800;
|
|
2010
|
+
let vpt = canvas.viewportTransform || [1, 0, 0, 1, 0, 0];
|
|
2011
|
+
vpt = [...vpt];
|
|
2012
|
+
const isFlipped = vpt[0] < 0;
|
|
2013
|
+
if (enabled && !isFlipped) {
|
|
2014
|
+
vpt[0] = -vpt[0];
|
|
2015
|
+
vpt[4] = width - vpt[4];
|
|
2016
|
+
canvas.setViewportTransform(vpt);
|
|
2017
|
+
canvas.requestRenderAll();
|
|
2018
|
+
} else if (!enabled && isFlipped) {
|
|
2019
|
+
vpt[0] = -vpt[0];
|
|
2020
|
+
vpt[4] = width - vpt[4];
|
|
2021
|
+
canvas.setViewportTransform(vpt);
|
|
2022
|
+
canvas.requestRenderAll();
|
|
2023
|
+
}
|
|
2024
|
+
}
|
|
2025
|
+
};
|
|
1687
2026
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1688
2027
|
0 && (module.exports = {
|
|
1689
2028
|
BackgroundTool,
|
|
@@ -1691,6 +2030,7 @@ var RulerTool = class {
|
|
|
1691
2030
|
FilmTool,
|
|
1692
2031
|
HoleTool,
|
|
1693
2032
|
ImageTool,
|
|
2033
|
+
MirrorTool,
|
|
1694
2034
|
RulerTool,
|
|
1695
2035
|
WhiteInkTool
|
|
1696
2036
|
});
|