@pooder/kit 5.0.0 → 5.0.2
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/.test-dist/src/dieline.js +118 -23
- package/.test-dist/src/feature.js +2 -0
- package/CHANGELOG.md +12 -0
- package/dist/index.d.mts +4 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +162 -56
- package/dist/index.mjs +165 -59
- package/package.json +1 -1
- package/src/dieline.ts +132 -24
- package/src/image.ts +38 -24
package/dist/index.mjs
CHANGED
|
@@ -205,7 +205,7 @@ var BackgroundTool = class {
|
|
|
205
205
|
import {
|
|
206
206
|
ContributionPointIds as ContributionPointIds2
|
|
207
207
|
} from "@pooder/core";
|
|
208
|
-
import { Path, Pattern } from "fabric";
|
|
208
|
+
import { Canvas as FabricCanvas, Path, Pattern } from "fabric";
|
|
209
209
|
|
|
210
210
|
// src/tracer.ts
|
|
211
211
|
import paper from "paper";
|
|
@@ -1756,6 +1756,7 @@ function buildSceneGeometry(configService, layout) {
|
|
|
1756
1756
|
}
|
|
1757
1757
|
|
|
1758
1758
|
// src/dieline.ts
|
|
1759
|
+
var IMAGE_OBJECT_LAYER_ID = "image.user";
|
|
1759
1760
|
var DielineTool = class {
|
|
1760
1761
|
constructor(options) {
|
|
1761
1762
|
this.id = "pooder.kit.dieline";
|
|
@@ -2082,8 +2083,8 @@ var DielineTool = class {
|
|
|
2082
2083
|
{
|
|
2083
2084
|
command: "exportCutImage",
|
|
2084
2085
|
title: "Export Cut Image",
|
|
2085
|
-
handler: () => {
|
|
2086
|
-
return this.exportCutImage();
|
|
2086
|
+
handler: (options) => {
|
|
2087
|
+
return this.exportCutImage(options);
|
|
2087
2088
|
}
|
|
2088
2089
|
},
|
|
2089
2090
|
{
|
|
@@ -2423,18 +2424,29 @@ var DielineTool = class {
|
|
|
2423
2424
|
pathData: this.state.pathData
|
|
2424
2425
|
};
|
|
2425
2426
|
}
|
|
2426
|
-
async exportCutImage() {
|
|
2427
|
-
|
|
2427
|
+
async exportCutImage(options) {
|
|
2428
|
+
var _a, _b;
|
|
2429
|
+
const debug = (options == null ? void 0 : options.debug) === true;
|
|
2430
|
+
if (!this.canvasService) {
|
|
2431
|
+
console.warn("[DielineTool] exportCutImage returned null: canvas-not-ready");
|
|
2432
|
+
return null;
|
|
2433
|
+
}
|
|
2428
2434
|
const configService = this.getConfigService();
|
|
2429
|
-
if (!configService)
|
|
2430
|
-
|
|
2431
|
-
|
|
2435
|
+
if (!configService) {
|
|
2436
|
+
console.warn(
|
|
2437
|
+
"[DielineTool] exportCutImage returned null: config-service-not-ready"
|
|
2438
|
+
);
|
|
2439
|
+
return null;
|
|
2440
|
+
}
|
|
2432
2441
|
this.syncSizeState(configService);
|
|
2433
2442
|
const sceneLayout = computeSceneLayout(
|
|
2434
2443
|
this.canvasService,
|
|
2435
2444
|
readSizeState(configService)
|
|
2436
2445
|
);
|
|
2437
|
-
if (!sceneLayout)
|
|
2446
|
+
if (!sceneLayout) {
|
|
2447
|
+
console.warn("[DielineTool] exportCutImage returned null: scene-layout-null");
|
|
2448
|
+
return null;
|
|
2449
|
+
}
|
|
2438
2450
|
const { shape, radius, features, pathData } = this.state;
|
|
2439
2451
|
const canvasW = sceneLayout.canvasWidth || this.canvasService.canvas.width || 800;
|
|
2440
2452
|
const canvasH = sceneLayout.canvasHeight || this.canvasService.canvas.height || 600;
|
|
@@ -2467,24 +2479,104 @@ var DielineTool = class {
|
|
|
2467
2479
|
canvasWidth: canvasW,
|
|
2468
2480
|
canvasHeight: canvasH
|
|
2469
2481
|
});
|
|
2470
|
-
const clonedLayer = await userLayer.clone();
|
|
2471
2482
|
const clipPath = new Path(generatedPathData, {
|
|
2472
|
-
originX: "
|
|
2473
|
-
originY: "
|
|
2474
|
-
left:
|
|
2475
|
-
top:
|
|
2483
|
+
originX: "center",
|
|
2484
|
+
originY: "center",
|
|
2485
|
+
left: cx,
|
|
2486
|
+
top: cy,
|
|
2476
2487
|
absolutePositioned: true
|
|
2477
2488
|
});
|
|
2478
|
-
|
|
2479
|
-
const
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2489
|
+
const pathOffsetX = Number((_a = clipPath == null ? void 0 : clipPath.pathOffset) == null ? void 0 : _a.x);
|
|
2490
|
+
const pathOffsetY = Number((_b = clipPath == null ? void 0 : clipPath.pathOffset) == null ? void 0 : _b.y);
|
|
2491
|
+
const centerX = Number.isFinite(pathOffsetX) ? pathOffsetX : cx;
|
|
2492
|
+
const centerY = Number.isFinite(pathOffsetY) ? pathOffsetY : cy;
|
|
2493
|
+
clipPath.set({
|
|
2494
|
+
originX: "center",
|
|
2495
|
+
originY: "center",
|
|
2496
|
+
left: centerX,
|
|
2497
|
+
top: centerY,
|
|
2498
|
+
absolutePositioned: true
|
|
2499
|
+
});
|
|
2500
|
+
clipPath.setCoords();
|
|
2501
|
+
const pathBounds = clipPath.getBoundingRect();
|
|
2502
|
+
if (!Number.isFinite(pathBounds.left) || !Number.isFinite(pathBounds.top) || !Number.isFinite(pathBounds.width) || !Number.isFinite(pathBounds.height) || pathBounds.width <= 0 || pathBounds.height <= 0) {
|
|
2503
|
+
console.warn("[DielineTool] exportCutImage returned null: invalid-cut-bounds", {
|
|
2504
|
+
bounds: pathBounds
|
|
2505
|
+
});
|
|
2506
|
+
return null;
|
|
2507
|
+
}
|
|
2508
|
+
const exportBounds = pathBounds;
|
|
2509
|
+
const sourceImages = this.canvasService.canvas.getObjects().filter((obj) => {
|
|
2510
|
+
var _a2;
|
|
2511
|
+
return ((_a2 = obj == null ? void 0 : obj.data) == null ? void 0 : _a2.layerId) === IMAGE_OBJECT_LAYER_ID;
|
|
2512
|
+
});
|
|
2513
|
+
if (!sourceImages.length) {
|
|
2514
|
+
console.warn(
|
|
2515
|
+
"[DielineTool] exportCutImage returned null: no-image-objects-on-canvas"
|
|
2516
|
+
);
|
|
2517
|
+
return null;
|
|
2518
|
+
}
|
|
2519
|
+
const sourceCanvasWidth = Number(
|
|
2520
|
+
this.canvasService.canvas.width || sceneLayout.canvasWidth || canvasW
|
|
2521
|
+
);
|
|
2522
|
+
const sourceCanvasHeight = Number(
|
|
2523
|
+
this.canvasService.canvas.height || sceneLayout.canvasHeight || canvasH
|
|
2524
|
+
);
|
|
2525
|
+
const el = document.createElement("canvas");
|
|
2526
|
+
const exportCanvas = new FabricCanvas(el, {
|
|
2527
|
+
renderOnAddRemove: false,
|
|
2528
|
+
selection: false,
|
|
2529
|
+
enableRetinaScaling: false,
|
|
2530
|
+
preserveObjectStacking: true
|
|
2531
|
+
});
|
|
2532
|
+
exportCanvas.setDimensions({
|
|
2533
|
+
width: Math.max(1, sourceCanvasWidth),
|
|
2534
|
+
height: Math.max(1, sourceCanvasHeight)
|
|
2487
2535
|
});
|
|
2536
|
+
try {
|
|
2537
|
+
for (const source of sourceImages) {
|
|
2538
|
+
const clone = await source.clone();
|
|
2539
|
+
clone.set({
|
|
2540
|
+
selectable: false,
|
|
2541
|
+
evented: false
|
|
2542
|
+
});
|
|
2543
|
+
clone.setCoords();
|
|
2544
|
+
exportCanvas.add(clone);
|
|
2545
|
+
}
|
|
2546
|
+
exportCanvas.clipPath = clipPath;
|
|
2547
|
+
exportCanvas.renderAll();
|
|
2548
|
+
const dataUrl = exportCanvas.toDataURL({
|
|
2549
|
+
format: "png",
|
|
2550
|
+
multiplier: 2,
|
|
2551
|
+
left: exportBounds.left,
|
|
2552
|
+
top: exportBounds.top,
|
|
2553
|
+
width: exportBounds.width,
|
|
2554
|
+
height: exportBounds.height
|
|
2555
|
+
});
|
|
2556
|
+
if (debug) {
|
|
2557
|
+
console.info("[DielineTool] exportCutImage success", {
|
|
2558
|
+
sourceCount: sourceImages.length,
|
|
2559
|
+
bounds: exportBounds,
|
|
2560
|
+
rawPathBounds: pathBounds,
|
|
2561
|
+
pathOffset: {
|
|
2562
|
+
x: Number.isFinite(pathOffsetX) ? pathOffsetX : null,
|
|
2563
|
+
y: Number.isFinite(pathOffsetY) ? pathOffsetY : null
|
|
2564
|
+
},
|
|
2565
|
+
clipPathCenter: {
|
|
2566
|
+
x: centerX,
|
|
2567
|
+
y: centerY
|
|
2568
|
+
},
|
|
2569
|
+
cutRect: sceneLayout.cutRect,
|
|
2570
|
+
canvasSize: {
|
|
2571
|
+
width: Math.max(1, sourceCanvasWidth),
|
|
2572
|
+
height: Math.max(1, sourceCanvasHeight)
|
|
2573
|
+
}
|
|
2574
|
+
});
|
|
2575
|
+
}
|
|
2576
|
+
return dataUrl;
|
|
2577
|
+
} finally {
|
|
2578
|
+
exportCanvas.dispose();
|
|
2579
|
+
}
|
|
2488
2580
|
}
|
|
2489
2581
|
};
|
|
2490
2582
|
|
|
@@ -3575,8 +3667,8 @@ var FeatureTool = class {
|
|
|
3575
3667
|
import {
|
|
3576
3668
|
ContributionPointIds as ContributionPointIds5
|
|
3577
3669
|
} from "@pooder/core";
|
|
3578
|
-
import { Canvas as
|
|
3579
|
-
var
|
|
3670
|
+
import { Canvas as FabricCanvas2, Image as FabricImage, Point as Point2 } from "fabric";
|
|
3671
|
+
var IMAGE_OBJECT_LAYER_ID2 = "image.user";
|
|
3580
3672
|
var IMAGE_OVERLAY_LAYER_ID = "image-overlay";
|
|
3581
3673
|
var IMAGE_REPLACE_GUARD_MS = 2500;
|
|
3582
3674
|
var ImageTool = class {
|
|
@@ -3636,7 +3728,7 @@ var ImageTool = class {
|
|
|
3636
3728
|
const selectedImage = list.find(
|
|
3637
3729
|
(obj) => {
|
|
3638
3730
|
var _a2;
|
|
3639
|
-
return ((_a2 = obj == null ? void 0 : obj.data) == null ? void 0 : _a2.layerId) ===
|
|
3731
|
+
return ((_a2 = obj == null ? void 0 : obj.data) == null ? void 0 : _a2.layerId) === IMAGE_OBJECT_LAYER_ID2;
|
|
3640
3732
|
}
|
|
3641
3733
|
);
|
|
3642
3734
|
this.isImageSelectionActive = !!selectedImage;
|
|
@@ -3675,7 +3767,7 @@ var ImageTool = class {
|
|
|
3675
3767
|
const target = e == null ? void 0 : e.target;
|
|
3676
3768
|
const id = (_a = target == null ? void 0 : target.data) == null ? void 0 : _a.id;
|
|
3677
3769
|
const layerId = (_b = target == null ? void 0 : target.data) == null ? void 0 : _b.layerId;
|
|
3678
|
-
if (typeof id !== "string" || layerId !==
|
|
3770
|
+
if (typeof id !== "string" || layerId !== IMAGE_OBJECT_LAYER_ID2) return;
|
|
3679
3771
|
const frame = this.getFrameRect();
|
|
3680
3772
|
if (!frame.width || !frame.height) return;
|
|
3681
3773
|
const center = target.getCenterPoint ? target.getCenterPoint() : new Point2((_c = target.left) != null ? _c : 0, (_d = target.top) != null ? _d : 0);
|
|
@@ -3706,10 +3798,7 @@ var ImageTool = class {
|
|
|
3706
3798
|
context.eventBus.on("selection:created", this.onSelectionChanged);
|
|
3707
3799
|
context.eventBus.on("selection:updated", this.onSelectionChanged);
|
|
3708
3800
|
context.eventBus.on("selection:cleared", this.onSelectionCleared);
|
|
3709
|
-
context.eventBus.on(
|
|
3710
|
-
"scene:layout:change",
|
|
3711
|
-
this.onSceneLayoutChanged
|
|
3712
|
-
);
|
|
3801
|
+
context.eventBus.on("scene:layout:change", this.onSceneLayoutChanged);
|
|
3713
3802
|
const configService = context.services.get(
|
|
3714
3803
|
"ConfigurationService"
|
|
3715
3804
|
);
|
|
@@ -3749,10 +3838,7 @@ var ImageTool = class {
|
|
|
3749
3838
|
context.eventBus.off("selection:created", this.onSelectionChanged);
|
|
3750
3839
|
context.eventBus.off("selection:updated", this.onSelectionChanged);
|
|
3751
3840
|
context.eventBus.off("selection:cleared", this.onSelectionCleared);
|
|
3752
|
-
context.eventBus.off(
|
|
3753
|
-
"scene:layout:change",
|
|
3754
|
-
this.onSceneLayoutChanged
|
|
3755
|
-
);
|
|
3841
|
+
context.eventBus.off("scene:layout:change", this.onSceneLayoutChanged);
|
|
3756
3842
|
(_a = this.dirtyTrackerDisposable) == null ? void 0 : _a.dispose();
|
|
3757
3843
|
this.dirtyTrackerDisposable = void 0;
|
|
3758
3844
|
this.clearRenderedImages();
|
|
@@ -3861,7 +3947,7 @@ var ImageTool = class {
|
|
|
3861
3947
|
id: "image.frame.outerBackground",
|
|
3862
3948
|
type: "color",
|
|
3863
3949
|
label: "Image Frame Outer Background",
|
|
3864
|
-
default: "
|
|
3950
|
+
default: "#f5f5f5"
|
|
3865
3951
|
}
|
|
3866
3952
|
],
|
|
3867
3953
|
[ContributionPointIds5.COMMANDS]: [
|
|
@@ -3904,6 +3990,7 @@ var ImageTool = class {
|
|
|
3904
3990
|
this.workingItems = this.cloneItems(this.items);
|
|
3905
3991
|
this.hasWorkingChanges = false;
|
|
3906
3992
|
this.updateImages();
|
|
3993
|
+
this.emitWorkingChange();
|
|
3907
3994
|
}
|
|
3908
3995
|
},
|
|
3909
3996
|
{
|
|
@@ -4018,13 +4105,20 @@ var ImageTool = class {
|
|
|
4018
4105
|
cloneItems(items) {
|
|
4019
4106
|
return this.normalizeItems((items || []).map((i) => ({ ...i })));
|
|
4020
4107
|
}
|
|
4108
|
+
emitWorkingChange(changedId = null) {
|
|
4109
|
+
var _a;
|
|
4110
|
+
(_a = this.context) == null ? void 0 : _a.eventBus.emit("image:working:change", {
|
|
4111
|
+
changedId,
|
|
4112
|
+
items: this.cloneItems(this.workingItems)
|
|
4113
|
+
});
|
|
4114
|
+
}
|
|
4021
4115
|
generateId() {
|
|
4022
4116
|
return Math.random().toString(36).substring(2, 9);
|
|
4023
4117
|
}
|
|
4024
4118
|
getImageIdFromActiveObject() {
|
|
4025
4119
|
var _a, _b, _c;
|
|
4026
4120
|
const active = (_a = this.canvasService) == null ? void 0 : _a.canvas.getActiveObject();
|
|
4027
|
-
if (((_b = active == null ? void 0 : active.data) == null ? void 0 : _b.layerId) ===
|
|
4121
|
+
if (((_b = active == null ? void 0 : active.data) == null ? void 0 : _b.layerId) === IMAGE_OBJECT_LAYER_ID2 && typeof ((_c = active == null ? void 0 : active.data) == null ? void 0 : _c.id) === "string") {
|
|
4028
4122
|
return active.data.id;
|
|
4029
4123
|
}
|
|
4030
4124
|
return null;
|
|
@@ -4086,6 +4180,7 @@ var ImageTool = class {
|
|
|
4086
4180
|
if (this.workingItems.some((existing) => existing.id === item.id)) return;
|
|
4087
4181
|
this.workingItems = this.cloneItems([...this.workingItems, item]);
|
|
4088
4182
|
this.updateImages();
|
|
4183
|
+
this.emitWorkingChange(item.id);
|
|
4089
4184
|
}
|
|
4090
4185
|
async updateImage(id, updates, options = {}) {
|
|
4091
4186
|
this.syncToolActiveFromWorkbench();
|
|
@@ -4193,7 +4288,7 @@ var ImageTool = class {
|
|
|
4193
4288
|
if (!this.canvasService) return [];
|
|
4194
4289
|
return this.canvasService.canvas.getObjects().filter((obj) => {
|
|
4195
4290
|
var _a;
|
|
4196
|
-
return ((_a = obj == null ? void 0 : obj.data) == null ? void 0 : _a.layerId) ===
|
|
4291
|
+
return ((_a = obj == null ? void 0 : obj.data) == null ? void 0 : _a.layerId) === IMAGE_OBJECT_LAYER_ID2;
|
|
4197
4292
|
});
|
|
4198
4293
|
}
|
|
4199
4294
|
getOverlayObjects() {
|
|
@@ -4269,10 +4364,7 @@ var ImageTool = class {
|
|
|
4269
4364
|
"image.frame.innerBackground",
|
|
4270
4365
|
"rgba(0,0,0,0)"
|
|
4271
4366
|
) || "rgba(0,0,0,0)",
|
|
4272
|
-
outerBackground:
|
|
4273
|
-
"image.frame.outerBackground",
|
|
4274
|
-
"rgba(0,0,0,0.18)"
|
|
4275
|
-
) || "rgba(0,0,0,0.18)"
|
|
4367
|
+
outerBackground: "#f5f5f5"
|
|
4276
4368
|
};
|
|
4277
4369
|
}
|
|
4278
4370
|
resolveRenderImageState(item) {
|
|
@@ -4349,7 +4441,7 @@ var ImageTool = class {
|
|
|
4349
4441
|
created.set({
|
|
4350
4442
|
data: {
|
|
4351
4443
|
id: item.id,
|
|
4352
|
-
layerId:
|
|
4444
|
+
layerId: IMAGE_OBJECT_LAYER_ID2,
|
|
4353
4445
|
type: "image-item"
|
|
4354
4446
|
}
|
|
4355
4447
|
});
|
|
@@ -4364,7 +4456,7 @@ var ImageTool = class {
|
|
|
4364
4456
|
data: {
|
|
4365
4457
|
...obj.data || {},
|
|
4366
4458
|
id: item.id,
|
|
4367
|
-
layerId:
|
|
4459
|
+
layerId: IMAGE_OBJECT_LAYER_ID2,
|
|
4368
4460
|
type: "image-item"
|
|
4369
4461
|
}
|
|
4370
4462
|
});
|
|
@@ -4416,10 +4508,21 @@ var ImageTool = class {
|
|
|
4416
4508
|
const canvasW = this.canvasService.canvas.width || 0;
|
|
4417
4509
|
const canvasH = this.canvasService.canvas.height || 0;
|
|
4418
4510
|
const visual = this.getFrameVisualConfig();
|
|
4419
|
-
const
|
|
4420
|
-
const
|
|
4421
|
-
const
|
|
4422
|
-
|
|
4511
|
+
const frameLeft = Math.max(0, Math.min(canvasW, frame.left));
|
|
4512
|
+
const frameTop = Math.max(0, Math.min(canvasH, frame.top));
|
|
4513
|
+
const frameRight = Math.max(
|
|
4514
|
+
frameLeft,
|
|
4515
|
+
Math.min(canvasW, frame.left + frame.width)
|
|
4516
|
+
);
|
|
4517
|
+
const frameBottom = Math.max(
|
|
4518
|
+
frameTop,
|
|
4519
|
+
Math.min(canvasH, frame.top + frame.height)
|
|
4520
|
+
);
|
|
4521
|
+
const visibleFrameH = Math.max(0, frameBottom - frameTop);
|
|
4522
|
+
const topH = frameTop;
|
|
4523
|
+
const bottomH = Math.max(0, canvasH - frameBottom);
|
|
4524
|
+
const leftW = frameLeft;
|
|
4525
|
+
const rightW = Math.max(0, canvasW - frameRight);
|
|
4423
4526
|
const mask = [
|
|
4424
4527
|
{
|
|
4425
4528
|
id: "image.cropMask.top",
|
|
@@ -4443,7 +4546,7 @@ var ImageTool = class {
|
|
|
4443
4546
|
data: { id: "image.cropMask.bottom", zIndex: 2 },
|
|
4444
4547
|
props: {
|
|
4445
4548
|
left: canvasW / 2,
|
|
4446
|
-
top:
|
|
4549
|
+
top: frameBottom + bottomH / 2,
|
|
4447
4550
|
width: canvasW,
|
|
4448
4551
|
height: bottomH,
|
|
4449
4552
|
originX: "center",
|
|
@@ -4459,9 +4562,9 @@ var ImageTool = class {
|
|
|
4459
4562
|
data: { id: "image.cropMask.left", zIndex: 3 },
|
|
4460
4563
|
props: {
|
|
4461
4564
|
left: leftW / 2,
|
|
4462
|
-
top:
|
|
4565
|
+
top: frameTop + visibleFrameH / 2,
|
|
4463
4566
|
width: leftW,
|
|
4464
|
-
height:
|
|
4567
|
+
height: visibleFrameH,
|
|
4465
4568
|
originX: "center",
|
|
4466
4569
|
originY: "center",
|
|
4467
4570
|
fill: visual.outerBackground,
|
|
@@ -4474,10 +4577,10 @@ var ImageTool = class {
|
|
|
4474
4577
|
type: "rect",
|
|
4475
4578
|
data: { id: "image.cropMask.right", zIndex: 4 },
|
|
4476
4579
|
props: {
|
|
4477
|
-
left:
|
|
4478
|
-
top:
|
|
4580
|
+
left: frameRight + rightW / 2,
|
|
4581
|
+
top: frameTop + visibleFrameH / 2,
|
|
4479
4582
|
width: rightW,
|
|
4480
|
-
height:
|
|
4583
|
+
height: visibleFrameH,
|
|
4481
4584
|
originX: "center",
|
|
4482
4585
|
originY: "center",
|
|
4483
4586
|
fill: visual.outerBackground,
|
|
@@ -4567,6 +4670,7 @@ var ImageTool = class {
|
|
|
4567
4670
|
if (this.isToolActive) {
|
|
4568
4671
|
this.updateImages();
|
|
4569
4672
|
}
|
|
4673
|
+
this.emitWorkingChange(id);
|
|
4570
4674
|
}
|
|
4571
4675
|
async updateImageInConfig(id, updates) {
|
|
4572
4676
|
var _a, _b, _c, _d;
|
|
@@ -4647,6 +4751,7 @@ var ImageTool = class {
|
|
|
4647
4751
|
this.isImageSelectionActive = true;
|
|
4648
4752
|
this.focusedImageId = id;
|
|
4649
4753
|
this.updateImages();
|
|
4754
|
+
this.emitWorkingChange(id);
|
|
4650
4755
|
}
|
|
4651
4756
|
focusImageSelection(id) {
|
|
4652
4757
|
if (!this.canvasService) return;
|
|
@@ -4739,6 +4844,7 @@ var ImageTool = class {
|
|
|
4739
4844
|
this.hasWorkingChanges = false;
|
|
4740
4845
|
this.workingItems = this.cloneItems(next);
|
|
4741
4846
|
this.updateConfig(next);
|
|
4847
|
+
this.emitWorkingChange(focusId);
|
|
4742
4848
|
if (focusId) {
|
|
4743
4849
|
this.focusedImageId = focusId;
|
|
4744
4850
|
this.isImageSelectionActive = true;
|
|
@@ -4758,7 +4864,7 @@ var ImageTool = class {
|
|
|
4758
4864
|
const width = Math.max(1, Math.round(frame.width * multiplier));
|
|
4759
4865
|
const height = Math.max(1, Math.round(frame.height * multiplier));
|
|
4760
4866
|
const el = document.createElement("canvas");
|
|
4761
|
-
const tempCanvas = new
|
|
4867
|
+
const tempCanvas = new FabricCanvas2(el, {
|
|
4762
4868
|
renderOnAddRemove: false,
|
|
4763
4869
|
selection: false,
|
|
4764
4870
|
enableRetinaScaling: false,
|
|
@@ -4768,7 +4874,7 @@ var ImageTool = class {
|
|
|
4768
4874
|
const idSet = new Set(imageIds);
|
|
4769
4875
|
const sourceObjects = this.canvasService.canvas.getObjects().filter((obj) => {
|
|
4770
4876
|
var _a2, _b2;
|
|
4771
|
-
return ((_a2 = obj == null ? void 0 : obj.data) == null ? void 0 : _a2.layerId) ===
|
|
4877
|
+
return ((_a2 = obj == null ? void 0 : obj.data) == null ? void 0 : _a2.layerId) === IMAGE_OBJECT_LAYER_ID2 && typeof ((_b2 = obj == null ? void 0 : obj.data) == null ? void 0 : _b2.id) === "string" && idSet.has(obj.data.id);
|
|
4772
4878
|
});
|
|
4773
4879
|
for (const source of sourceObjects) {
|
|
4774
4880
|
const clone = await source.clone();
|
|
@@ -4815,7 +4921,7 @@ import {
|
|
|
4815
4921
|
} from "@pooder/core";
|
|
4816
4922
|
import { Image as FabricImage2 } from "fabric";
|
|
4817
4923
|
var WHITE_INK_OBJECT_LAYER_ID = "white-ink.user";
|
|
4818
|
-
var
|
|
4924
|
+
var IMAGE_OBJECT_LAYER_ID3 = "image.user";
|
|
4819
4925
|
var WHITE_INK_DEBUG_KEY = "whiteInk.debug";
|
|
4820
4926
|
var WHITE_INK_PREVIEW_IMAGE_VISIBLE_KEY = "whiteInk.previewImageVisible";
|
|
4821
4927
|
var WHITE_INK_DEFAULT_OPACITY = 0.85;
|
|
@@ -5516,7 +5622,7 @@ var WhiteInkTool = class {
|
|
|
5516
5622
|
const imageIndexes = objects.map(
|
|
5517
5623
|
(obj, index) => {
|
|
5518
5624
|
var _a;
|
|
5519
|
-
return ((_a = obj == null ? void 0 : obj.data) == null ? void 0 : _a.layerId) ===
|
|
5625
|
+
return ((_a = obj == null ? void 0 : obj.data) == null ? void 0 : _a.layerId) === IMAGE_OBJECT_LAYER_ID3 ? index : -1;
|
|
5520
5626
|
}
|
|
5521
5627
|
).filter((index) => index >= 0);
|
|
5522
5628
|
if (imageIndexes.length > 0) {
|
|
@@ -5549,7 +5655,7 @@ var WhiteInkTool = class {
|
|
|
5549
5655
|
let changed = false;
|
|
5550
5656
|
this.canvasService.canvas.getObjects().forEach((obj) => {
|
|
5551
5657
|
var _a, _b;
|
|
5552
|
-
if (((_a = obj == null ? void 0 : obj.data) == null ? void 0 : _a.layerId) !==
|
|
5658
|
+
if (((_a = obj == null ? void 0 : obj.data) == null ? void 0 : _a.layerId) !== IMAGE_OBJECT_LAYER_ID3) return;
|
|
5553
5659
|
if (obj.visible === visible) return;
|
|
5554
5660
|
obj.set({ visible });
|
|
5555
5661
|
(_b = obj.setCoords) == null ? void 0 : _b.call(obj);
|
package/package.json
CHANGED
package/src/dieline.ts
CHANGED
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
ConfigurationContribution,
|
|
7
7
|
ConfigurationService,
|
|
8
8
|
} from "@pooder/core";
|
|
9
|
-
import { Path, Pattern } from "fabric";
|
|
9
|
+
import { Canvas as FabricCanvas, Path, Pattern } from "fabric";
|
|
10
10
|
import CanvasService from "./CanvasService";
|
|
11
11
|
import { ImageTracer } from "./tracer";
|
|
12
12
|
import { Unit } from "./coordinate";
|
|
@@ -63,6 +63,8 @@ export interface DielineState {
|
|
|
63
63
|
pathData?: string;
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
+
const IMAGE_OBJECT_LAYER_ID = "image.user";
|
|
67
|
+
|
|
66
68
|
export class DielineTool implements Extension {
|
|
67
69
|
id = "pooder.kit.dieline";
|
|
68
70
|
public metadata = {
|
|
@@ -424,8 +426,8 @@ export class DielineTool implements Extension {
|
|
|
424
426
|
{
|
|
425
427
|
command: "exportCutImage",
|
|
426
428
|
title: "Export Cut Image",
|
|
427
|
-
handler: () => {
|
|
428
|
-
return this.exportCutImage();
|
|
429
|
+
handler: (options?: { debug?: boolean }) => {
|
|
430
|
+
return this.exportCutImage(options);
|
|
429
431
|
},
|
|
430
432
|
},
|
|
431
433
|
{
|
|
@@ -824,19 +826,30 @@ export class DielineTool implements Extension {
|
|
|
824
826
|
} as DielineGeometry;
|
|
825
827
|
}
|
|
826
828
|
|
|
827
|
-
public async exportCutImage() {
|
|
828
|
-
|
|
829
|
+
public async exportCutImage(options?: { debug?: boolean }) {
|
|
830
|
+
const debug = options?.debug === true;
|
|
831
|
+
|
|
832
|
+
if (!this.canvasService) {
|
|
833
|
+
console.warn("[DielineTool] exportCutImage returned null: canvas-not-ready");
|
|
834
|
+
return null;
|
|
835
|
+
}
|
|
829
836
|
const configService = this.getConfigService();
|
|
830
|
-
if (!configService)
|
|
831
|
-
|
|
832
|
-
|
|
837
|
+
if (!configService) {
|
|
838
|
+
console.warn(
|
|
839
|
+
"[DielineTool] exportCutImage returned null: config-service-not-ready",
|
|
840
|
+
);
|
|
841
|
+
return null;
|
|
842
|
+
}
|
|
833
843
|
|
|
834
844
|
this.syncSizeState(configService);
|
|
835
845
|
const sceneLayout = computeSceneLayout(
|
|
836
846
|
this.canvasService,
|
|
837
847
|
readSizeState(configService),
|
|
838
848
|
);
|
|
839
|
-
if (!sceneLayout)
|
|
849
|
+
if (!sceneLayout) {
|
|
850
|
+
console.warn("[DielineTool] exportCutImage returned null: scene-layout-null");
|
|
851
|
+
return null;
|
|
852
|
+
}
|
|
840
853
|
|
|
841
854
|
const { shape, radius, features, pathData } = this.state;
|
|
842
855
|
const canvasW = sceneLayout.canvasWidth || this.canvasService.canvas.width || 800;
|
|
@@ -874,24 +887,119 @@ export class DielineTool implements Extension {
|
|
|
874
887
|
canvasHeight: canvasH,
|
|
875
888
|
});
|
|
876
889
|
|
|
877
|
-
const clonedLayer = await userLayer.clone();
|
|
878
890
|
const clipPath = new Path(generatedPathData, {
|
|
879
|
-
originX: "
|
|
880
|
-
originY: "
|
|
881
|
-
left:
|
|
882
|
-
top:
|
|
891
|
+
originX: "center",
|
|
892
|
+
originY: "center",
|
|
893
|
+
left: cx,
|
|
894
|
+
top: cy,
|
|
883
895
|
absolutePositioned: true,
|
|
884
896
|
});
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
const
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
897
|
+
const pathOffsetX = Number((clipPath as any)?.pathOffset?.x);
|
|
898
|
+
const pathOffsetY = Number((clipPath as any)?.pathOffset?.y);
|
|
899
|
+
const centerX = Number.isFinite(pathOffsetX) ? pathOffsetX : cx;
|
|
900
|
+
const centerY = Number.isFinite(pathOffsetY) ? pathOffsetY : cy;
|
|
901
|
+
clipPath.set({
|
|
902
|
+
originX: "center",
|
|
903
|
+
originY: "center",
|
|
904
|
+
left: centerX,
|
|
905
|
+
top: centerY,
|
|
906
|
+
absolutePositioned: true,
|
|
895
907
|
});
|
|
908
|
+
clipPath.setCoords();
|
|
909
|
+
|
|
910
|
+
const pathBounds = clipPath.getBoundingRect();
|
|
911
|
+
if (
|
|
912
|
+
!Number.isFinite(pathBounds.left) ||
|
|
913
|
+
!Number.isFinite(pathBounds.top) ||
|
|
914
|
+
!Number.isFinite(pathBounds.width) ||
|
|
915
|
+
!Number.isFinite(pathBounds.height) ||
|
|
916
|
+
pathBounds.width <= 0 ||
|
|
917
|
+
pathBounds.height <= 0
|
|
918
|
+
) {
|
|
919
|
+
console.warn("[DielineTool] exportCutImage returned null: invalid-cut-bounds", {
|
|
920
|
+
bounds: pathBounds,
|
|
921
|
+
});
|
|
922
|
+
return null;
|
|
923
|
+
}
|
|
924
|
+
const exportBounds = pathBounds;
|
|
925
|
+
|
|
926
|
+
const sourceImages = this.canvasService.canvas.getObjects().filter((obj: any) => {
|
|
927
|
+
return obj?.data?.layerId === IMAGE_OBJECT_LAYER_ID;
|
|
928
|
+
});
|
|
929
|
+
if (!sourceImages.length) {
|
|
930
|
+
console.warn(
|
|
931
|
+
"[DielineTool] exportCutImage returned null: no-image-objects-on-canvas",
|
|
932
|
+
);
|
|
933
|
+
return null;
|
|
934
|
+
}
|
|
935
|
+
|
|
936
|
+
const sourceCanvasWidth = Number(
|
|
937
|
+
this.canvasService.canvas.width || sceneLayout.canvasWidth || canvasW,
|
|
938
|
+
);
|
|
939
|
+
const sourceCanvasHeight = Number(
|
|
940
|
+
this.canvasService.canvas.height || sceneLayout.canvasHeight || canvasH,
|
|
941
|
+
);
|
|
942
|
+
|
|
943
|
+
const el = document.createElement("canvas");
|
|
944
|
+
const exportCanvas = new FabricCanvas(el, {
|
|
945
|
+
renderOnAddRemove: false,
|
|
946
|
+
selection: false,
|
|
947
|
+
enableRetinaScaling: false,
|
|
948
|
+
preserveObjectStacking: true,
|
|
949
|
+
} as any);
|
|
950
|
+
exportCanvas.setDimensions({
|
|
951
|
+
width: Math.max(1, sourceCanvasWidth),
|
|
952
|
+
height: Math.max(1, sourceCanvasHeight),
|
|
953
|
+
});
|
|
954
|
+
|
|
955
|
+
try {
|
|
956
|
+
for (const source of sourceImages as any[]) {
|
|
957
|
+
const clone = await source.clone();
|
|
958
|
+
clone.set({
|
|
959
|
+
selectable: false,
|
|
960
|
+
evented: false,
|
|
961
|
+
});
|
|
962
|
+
clone.setCoords();
|
|
963
|
+
exportCanvas.add(clone);
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
exportCanvas.clipPath = clipPath;
|
|
967
|
+
exportCanvas.renderAll();
|
|
968
|
+
|
|
969
|
+
const dataUrl = exportCanvas.toDataURL({
|
|
970
|
+
format: "png",
|
|
971
|
+
multiplier: 2,
|
|
972
|
+
left: exportBounds.left,
|
|
973
|
+
top: exportBounds.top,
|
|
974
|
+
width: exportBounds.width,
|
|
975
|
+
height: exportBounds.height,
|
|
976
|
+
});
|
|
977
|
+
|
|
978
|
+
if (debug) {
|
|
979
|
+
console.info("[DielineTool] exportCutImage success", {
|
|
980
|
+
sourceCount: sourceImages.length,
|
|
981
|
+
bounds: exportBounds,
|
|
982
|
+
rawPathBounds: pathBounds,
|
|
983
|
+
pathOffset: {
|
|
984
|
+
x: Number.isFinite(pathOffsetX) ? pathOffsetX : null,
|
|
985
|
+
y: Number.isFinite(pathOffsetY) ? pathOffsetY : null,
|
|
986
|
+
},
|
|
987
|
+
clipPathCenter: {
|
|
988
|
+
x: centerX,
|
|
989
|
+
y: centerY,
|
|
990
|
+
},
|
|
991
|
+
cutRect: sceneLayout.cutRect,
|
|
992
|
+
canvasSize: {
|
|
993
|
+
width: Math.max(1, sourceCanvasWidth),
|
|
994
|
+
height: Math.max(1, sourceCanvasHeight),
|
|
995
|
+
},
|
|
996
|
+
});
|
|
997
|
+
}
|
|
998
|
+
|
|
999
|
+
return dataUrl;
|
|
1000
|
+
} finally {
|
|
1001
|
+
exportCanvas.dispose();
|
|
1002
|
+
}
|
|
896
1003
|
}
|
|
1004
|
+
|
|
897
1005
|
}
|