@pooder/kit 6.1.1 → 6.2.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/.test-dist/src/extensions/background/BackgroundTool.js +177 -5
- package/.test-dist/src/extensions/constraintUtils.js +44 -0
- package/.test-dist/src/extensions/dieline/DielineTool.js +30 -400
- package/.test-dist/src/extensions/dieline/featureResolution.js +29 -0
- package/.test-dist/src/extensions/dieline/model.js +83 -0
- package/.test-dist/src/extensions/dieline/renderBuilder.js +211 -0
- package/.test-dist/src/extensions/feature/FeatureTool.js +136 -42
- package/.test-dist/src/extensions/image/ImageTool.js +281 -25
- package/.test-dist/src/shared/constants/layers.js +3 -1
- package/CHANGELOG.md +12 -0
- package/dist/index.d.mts +58 -6
- package/dist/index.d.ts +58 -6
- package/dist/index.js +989 -518
- package/dist/index.mjs +1014 -545
- package/package.json +1 -1
- package/src/extensions/background/BackgroundTool.ts +264 -4
- package/src/extensions/dieline/DielineTool.ts +38 -539
- package/src/extensions/dieline/model.ts +165 -1
- package/src/extensions/dieline/renderBuilder.ts +275 -0
- package/src/extensions/feature/FeatureTool.ts +167 -44
- package/src/extensions/image/ImageTool.ts +385 -29
- package/src/shared/constants/layers.ts +2 -0
|
@@ -14,7 +14,11 @@ import {
|
|
|
14
14
|
Point,
|
|
15
15
|
controlsUtils,
|
|
16
16
|
} from "fabric";
|
|
17
|
-
import {
|
|
17
|
+
import {
|
|
18
|
+
CanvasService,
|
|
19
|
+
RenderLayoutRect,
|
|
20
|
+
RenderObjectSpec,
|
|
21
|
+
} from "../../services";
|
|
18
22
|
import { isDielineShape, normalizeShapeStyle } from "../dielineShape";
|
|
19
23
|
import type { DielineShape, DielineShapeStyle } from "../dielineShape";
|
|
20
24
|
import { generateDielinePath, getPathBounds } from "../geometry";
|
|
@@ -140,11 +144,38 @@ interface ImageControlDescriptor {
|
|
|
140
144
|
create: () => Control;
|
|
141
145
|
}
|
|
142
146
|
|
|
147
|
+
type SnapAxis = "x" | "y";
|
|
148
|
+
type SnapLineKind = "edge" | "center";
|
|
149
|
+
type SnapLineId =
|
|
150
|
+
| "frame-left"
|
|
151
|
+
| "frame-center-x"
|
|
152
|
+
| "frame-right"
|
|
153
|
+
| "frame-top"
|
|
154
|
+
| "frame-center-y"
|
|
155
|
+
| "frame-bottom";
|
|
156
|
+
|
|
157
|
+
interface SnapMatch {
|
|
158
|
+
axis: SnapAxis;
|
|
159
|
+
lineId: SnapLineId;
|
|
160
|
+
kind: SnapLineKind;
|
|
161
|
+
lineScene: number;
|
|
162
|
+
deltaScene: number;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
interface SnapCandidate {
|
|
166
|
+
axis: SnapAxis;
|
|
167
|
+
lineId: SnapLineId;
|
|
168
|
+
kind: SnapLineKind;
|
|
169
|
+
lineScene: number;
|
|
170
|
+
deltaScene: number;
|
|
171
|
+
}
|
|
172
|
+
|
|
143
173
|
const IMAGE_DEFAULT_CONTROL_CAPABILITIES: ImageControlCapability[] = [
|
|
144
174
|
"rotate",
|
|
145
175
|
"scale",
|
|
146
176
|
];
|
|
147
177
|
|
|
178
|
+
const IMAGE_MOVE_SNAP_THRESHOLD_PX = 6;
|
|
148
179
|
const IMAGE_CONTROL_DESCRIPTORS: ImageControlDescriptor[] = [
|
|
149
180
|
{
|
|
150
181
|
key: "tl",
|
|
@@ -199,6 +230,14 @@ export class ImageTool implements Extension {
|
|
|
199
230
|
private cropShapeHatchPatternKey?: string;
|
|
200
231
|
private imageSpecs: RenderObjectSpec[] = [];
|
|
201
232
|
private overlaySpecs: RenderObjectSpec[] = [];
|
|
233
|
+
private activeSnapX: SnapMatch | null = null;
|
|
234
|
+
private activeSnapY: SnapMatch | null = null;
|
|
235
|
+
private movingImageId: string | null = null;
|
|
236
|
+
private hasRenderedSnapGuides = false;
|
|
237
|
+
private canvasObjectMovingHandler?: (e: any) => void;
|
|
238
|
+
private canvasMouseUpHandler?: (e: any) => void;
|
|
239
|
+
private canvasBeforeRenderHandler?: () => void;
|
|
240
|
+
private canvasAfterRenderHandler?: () => void;
|
|
202
241
|
private renderProducerDisposable?: { dispose: () => void };
|
|
203
242
|
private readonly subscriptions = new SubscriptionBag();
|
|
204
243
|
private imageControlsByCapabilityKey: Map<string, Record<string, Control>> =
|
|
@@ -247,9 +286,18 @@ export class ImageTool implements Extension {
|
|
|
247
286
|
}),
|
|
248
287
|
{ priority: 300 },
|
|
249
288
|
);
|
|
289
|
+
this.bindCanvasInteractionHandlers();
|
|
250
290
|
|
|
251
|
-
this.subscriptions.on(
|
|
252
|
-
|
|
291
|
+
this.subscriptions.on(
|
|
292
|
+
context.eventBus,
|
|
293
|
+
"tool:activated",
|
|
294
|
+
this.onToolActivated,
|
|
295
|
+
);
|
|
296
|
+
this.subscriptions.on(
|
|
297
|
+
context.eventBus,
|
|
298
|
+
"object:modified",
|
|
299
|
+
this.onObjectModified,
|
|
300
|
+
);
|
|
253
301
|
this.subscriptions.on(
|
|
254
302
|
context.eventBus,
|
|
255
303
|
"selection:created",
|
|
@@ -328,6 +376,8 @@ export class ImageTool implements Extension {
|
|
|
328
376
|
this.imageSpecs = [];
|
|
329
377
|
this.overlaySpecs = [];
|
|
330
378
|
this.imageControlsByCapabilityKey.clear();
|
|
379
|
+
this.endMoveSnapInteraction();
|
|
380
|
+
this.unbindCanvasInteractionHandlers();
|
|
331
381
|
|
|
332
382
|
this.clearRenderedImages();
|
|
333
383
|
this.renderProducerDisposable?.dispose();
|
|
@@ -347,6 +397,7 @@ export class ImageTool implements Extension {
|
|
|
347
397
|
const before = this.isToolActive;
|
|
348
398
|
this.syncToolActiveFromWorkbench(event.id);
|
|
349
399
|
if (!this.isToolActive) {
|
|
400
|
+
this.endMoveSnapInteraction();
|
|
350
401
|
this.setImageFocus(null, {
|
|
351
402
|
syncCanvasSelection: true,
|
|
352
403
|
skipRender: true,
|
|
@@ -396,6 +447,7 @@ export class ImageTool implements Extension {
|
|
|
396
447
|
};
|
|
397
448
|
|
|
398
449
|
private onSelectionCleared = () => {
|
|
450
|
+
this.endMoveSnapInteraction();
|
|
399
451
|
this.setImageFocus(null, {
|
|
400
452
|
syncCanvasSelection: false,
|
|
401
453
|
skipRender: true,
|
|
@@ -405,6 +457,7 @@ export class ImageTool implements Extension {
|
|
|
405
457
|
};
|
|
406
458
|
|
|
407
459
|
private onSceneLayoutChanged = () => {
|
|
460
|
+
this.canvasService?.requestRenderAll();
|
|
408
461
|
this.updateImages();
|
|
409
462
|
};
|
|
410
463
|
|
|
@@ -412,6 +465,330 @@ export class ImageTool implements Extension {
|
|
|
412
465
|
this.updateImages();
|
|
413
466
|
};
|
|
414
467
|
|
|
468
|
+
private bindCanvasInteractionHandlers() {
|
|
469
|
+
if (!this.canvasService || this.canvasObjectMovingHandler) return;
|
|
470
|
+
this.canvasMouseUpHandler = (e: any) => {
|
|
471
|
+
const target = this.getActiveImageTarget(e?.target);
|
|
472
|
+
if (
|
|
473
|
+
target &&
|
|
474
|
+
typeof target?.data?.id === "string" &&
|
|
475
|
+
target.data.id === this.movingImageId
|
|
476
|
+
) {
|
|
477
|
+
this.applyMoveSnapToTarget(target);
|
|
478
|
+
}
|
|
479
|
+
this.endMoveSnapInteraction();
|
|
480
|
+
};
|
|
481
|
+
this.canvasObjectMovingHandler = (e: any) => {
|
|
482
|
+
this.handleCanvasObjectMoving(e);
|
|
483
|
+
};
|
|
484
|
+
this.canvasBeforeRenderHandler = () => {
|
|
485
|
+
this.handleCanvasBeforeRender();
|
|
486
|
+
};
|
|
487
|
+
this.canvasAfterRenderHandler = () => {
|
|
488
|
+
this.handleCanvasAfterRender();
|
|
489
|
+
};
|
|
490
|
+
this.canvasService.canvas.on("mouse:up", this.canvasMouseUpHandler);
|
|
491
|
+
this.canvasService.canvas.on(
|
|
492
|
+
"object:moving",
|
|
493
|
+
this.canvasObjectMovingHandler,
|
|
494
|
+
);
|
|
495
|
+
this.canvasService.canvas.on(
|
|
496
|
+
"before:render",
|
|
497
|
+
this.canvasBeforeRenderHandler,
|
|
498
|
+
);
|
|
499
|
+
this.canvasService.canvas.on("after:render", this.canvasAfterRenderHandler);
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
private unbindCanvasInteractionHandlers() {
|
|
503
|
+
if (!this.canvasService) return;
|
|
504
|
+
if (this.canvasMouseUpHandler) {
|
|
505
|
+
this.canvasService.canvas.off("mouse:up", this.canvasMouseUpHandler);
|
|
506
|
+
}
|
|
507
|
+
if (this.canvasObjectMovingHandler) {
|
|
508
|
+
this.canvasService.canvas.off(
|
|
509
|
+
"object:moving",
|
|
510
|
+
this.canvasObjectMovingHandler,
|
|
511
|
+
);
|
|
512
|
+
}
|
|
513
|
+
if (this.canvasBeforeRenderHandler) {
|
|
514
|
+
this.canvasService.canvas.off(
|
|
515
|
+
"before:render",
|
|
516
|
+
this.canvasBeforeRenderHandler,
|
|
517
|
+
);
|
|
518
|
+
}
|
|
519
|
+
if (this.canvasAfterRenderHandler) {
|
|
520
|
+
this.canvasService.canvas.off(
|
|
521
|
+
"after:render",
|
|
522
|
+
this.canvasAfterRenderHandler,
|
|
523
|
+
);
|
|
524
|
+
}
|
|
525
|
+
this.canvasMouseUpHandler = undefined;
|
|
526
|
+
this.canvasObjectMovingHandler = undefined;
|
|
527
|
+
this.canvasBeforeRenderHandler = undefined;
|
|
528
|
+
this.canvasAfterRenderHandler = undefined;
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
private getActiveImageTarget(target: any): any | null {
|
|
532
|
+
if (!this.isToolActive) return null;
|
|
533
|
+
if (!target) return null;
|
|
534
|
+
if (target?.data?.layerId !== IMAGE_OBJECT_LAYER_ID) return null;
|
|
535
|
+
if (typeof target?.data?.id !== "string") return null;
|
|
536
|
+
return target;
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
private getTargetBoundsScene(target: any): FrameRect | null {
|
|
540
|
+
if (!this.canvasService || !target) return null;
|
|
541
|
+
const rawBounds =
|
|
542
|
+
typeof target.getBoundingRect === "function"
|
|
543
|
+
? target.getBoundingRect()
|
|
544
|
+
: {
|
|
545
|
+
left: Number(target.left || 0),
|
|
546
|
+
top: Number(target.top || 0),
|
|
547
|
+
width: Number(target.width || 0),
|
|
548
|
+
height: Number(target.height || 0),
|
|
549
|
+
};
|
|
550
|
+
return this.canvasService.toSceneRect({
|
|
551
|
+
left: Number(rawBounds.left || 0),
|
|
552
|
+
top: Number(rawBounds.top || 0),
|
|
553
|
+
width: Number(rawBounds.width || 0),
|
|
554
|
+
height: Number(rawBounds.height || 0),
|
|
555
|
+
});
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
private getSnapThresholdScene(px: number): number {
|
|
559
|
+
if (!this.canvasService) return px;
|
|
560
|
+
return this.canvasService.toSceneLength(px);
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
private pickSnapMatch(candidates: SnapCandidate[]): SnapMatch | null {
|
|
564
|
+
if (!candidates.length) return null;
|
|
565
|
+
|
|
566
|
+
const snapThreshold = this.getSnapThresholdScene(
|
|
567
|
+
IMAGE_MOVE_SNAP_THRESHOLD_PX,
|
|
568
|
+
);
|
|
569
|
+
|
|
570
|
+
let best: SnapCandidate | null = null;
|
|
571
|
+
candidates.forEach((candidate) => {
|
|
572
|
+
if (Math.abs(candidate.deltaScene) > snapThreshold) return;
|
|
573
|
+
if (!best || Math.abs(candidate.deltaScene) < Math.abs(best.deltaScene)) {
|
|
574
|
+
best = candidate;
|
|
575
|
+
}
|
|
576
|
+
});
|
|
577
|
+
return best;
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
private computeMoveSnapMatches(
|
|
581
|
+
bounds: FrameRect | null,
|
|
582
|
+
frame: FrameRect,
|
|
583
|
+
): { x: SnapMatch | null; y: SnapMatch | null } {
|
|
584
|
+
if (!bounds || frame.width <= 0 || frame.height <= 0) {
|
|
585
|
+
return { x: null, y: null };
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
const xCandidates: SnapCandidate[] = [
|
|
589
|
+
{
|
|
590
|
+
axis: "x",
|
|
591
|
+
lineId: "frame-left",
|
|
592
|
+
kind: "edge",
|
|
593
|
+
lineScene: frame.left,
|
|
594
|
+
deltaScene: frame.left - bounds.left,
|
|
595
|
+
},
|
|
596
|
+
{
|
|
597
|
+
axis: "x",
|
|
598
|
+
lineId: "frame-center-x",
|
|
599
|
+
kind: "center",
|
|
600
|
+
lineScene: frame.left + frame.width / 2,
|
|
601
|
+
deltaScene:
|
|
602
|
+
frame.left + frame.width / 2 - (bounds.left + bounds.width / 2),
|
|
603
|
+
},
|
|
604
|
+
{
|
|
605
|
+
axis: "x",
|
|
606
|
+
lineId: "frame-right",
|
|
607
|
+
kind: "edge",
|
|
608
|
+
lineScene: frame.left + frame.width,
|
|
609
|
+
deltaScene: frame.left + frame.width - (bounds.left + bounds.width),
|
|
610
|
+
},
|
|
611
|
+
];
|
|
612
|
+
const yCandidates: SnapCandidate[] = [
|
|
613
|
+
{
|
|
614
|
+
axis: "y",
|
|
615
|
+
lineId: "frame-top",
|
|
616
|
+
kind: "edge",
|
|
617
|
+
lineScene: frame.top,
|
|
618
|
+
deltaScene: frame.top - bounds.top,
|
|
619
|
+
},
|
|
620
|
+
{
|
|
621
|
+
axis: "y",
|
|
622
|
+
lineId: "frame-center-y",
|
|
623
|
+
kind: "center",
|
|
624
|
+
lineScene: frame.top + frame.height / 2,
|
|
625
|
+
deltaScene:
|
|
626
|
+
frame.top + frame.height / 2 - (bounds.top + bounds.height / 2),
|
|
627
|
+
},
|
|
628
|
+
{
|
|
629
|
+
axis: "y",
|
|
630
|
+
lineId: "frame-bottom",
|
|
631
|
+
kind: "edge",
|
|
632
|
+
lineScene: frame.top + frame.height,
|
|
633
|
+
deltaScene: frame.top + frame.height - (bounds.top + bounds.height),
|
|
634
|
+
},
|
|
635
|
+
];
|
|
636
|
+
|
|
637
|
+
return {
|
|
638
|
+
x: this.pickSnapMatch(xCandidates),
|
|
639
|
+
y: this.pickSnapMatch(yCandidates),
|
|
640
|
+
};
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
private areSnapMatchesEqual(
|
|
644
|
+
a: SnapMatch | null,
|
|
645
|
+
b: SnapMatch | null,
|
|
646
|
+
): boolean {
|
|
647
|
+
if (!a && !b) return true;
|
|
648
|
+
if (!a || !b) return false;
|
|
649
|
+
return a.lineId === b.lineId && a.axis === b.axis && a.kind === b.kind;
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
private updateSnapMatchState(
|
|
653
|
+
nextX: SnapMatch | null,
|
|
654
|
+
nextY: SnapMatch | null,
|
|
655
|
+
) {
|
|
656
|
+
const changed =
|
|
657
|
+
!this.areSnapMatchesEqual(this.activeSnapX, nextX) ||
|
|
658
|
+
!this.areSnapMatchesEqual(this.activeSnapY, nextY);
|
|
659
|
+
this.activeSnapX = nextX;
|
|
660
|
+
this.activeSnapY = nextY;
|
|
661
|
+
if (changed) {
|
|
662
|
+
this.canvasService?.requestRenderAll();
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
private clearSnapPreview() {
|
|
667
|
+
this.activeSnapX = null;
|
|
668
|
+
this.activeSnapY = null;
|
|
669
|
+
this.hasRenderedSnapGuides = false;
|
|
670
|
+
this.canvasService?.requestRenderAll();
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
private endMoveSnapInteraction() {
|
|
674
|
+
this.movingImageId = null;
|
|
675
|
+
this.clearSnapPreview();
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
private applyMoveSnapToTarget(target: any): {
|
|
679
|
+
x: SnapMatch | null;
|
|
680
|
+
y: SnapMatch | null;
|
|
681
|
+
} {
|
|
682
|
+
if (!this.canvasService) {
|
|
683
|
+
return { x: null, y: null };
|
|
684
|
+
}
|
|
685
|
+
const frame = this.getFrameRect();
|
|
686
|
+
if (frame.width <= 0 || frame.height <= 0) {
|
|
687
|
+
return { x: null, y: null };
|
|
688
|
+
}
|
|
689
|
+
const bounds = this.getTargetBoundsScene(target);
|
|
690
|
+
const matches = this.computeMoveSnapMatches(bounds, frame);
|
|
691
|
+
const deltaScreenX = this.canvasService.toScreenLength(
|
|
692
|
+
matches.x?.deltaScene ?? 0,
|
|
693
|
+
);
|
|
694
|
+
const deltaScreenY = this.canvasService.toScreenLength(
|
|
695
|
+
matches.y?.deltaScene ?? 0,
|
|
696
|
+
);
|
|
697
|
+
if (deltaScreenX || deltaScreenY) {
|
|
698
|
+
target.set({
|
|
699
|
+
left: Number(target.left || 0) + deltaScreenX,
|
|
700
|
+
top: Number(target.top || 0) + deltaScreenY,
|
|
701
|
+
});
|
|
702
|
+
target.setCoords();
|
|
703
|
+
}
|
|
704
|
+
return matches;
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
private handleCanvasBeforeRender() {
|
|
708
|
+
if (!this.canvasService) return;
|
|
709
|
+
if (!this.hasRenderedSnapGuides && !this.activeSnapX && !this.activeSnapY) {
|
|
710
|
+
return;
|
|
711
|
+
}
|
|
712
|
+
this.canvasService.canvas.clearContext(
|
|
713
|
+
this.canvasService.canvas.contextTop,
|
|
714
|
+
);
|
|
715
|
+
this.hasRenderedSnapGuides = false;
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
private drawSnapGuideLine(
|
|
719
|
+
from: { x: number; y: number },
|
|
720
|
+
to: { x: number; y: number },
|
|
721
|
+
) {
|
|
722
|
+
if (!this.canvasService) return;
|
|
723
|
+
const ctx = this.canvasService.canvas.contextTop;
|
|
724
|
+
if (!ctx) return;
|
|
725
|
+
const color =
|
|
726
|
+
this.getConfig<string>("image.control.borderColor", "#1677ff") ||
|
|
727
|
+
"#1677ff";
|
|
728
|
+
ctx.save();
|
|
729
|
+
ctx.strokeStyle = color;
|
|
730
|
+
ctx.lineWidth = 1;
|
|
731
|
+
ctx.beginPath();
|
|
732
|
+
ctx.moveTo(from.x, from.y);
|
|
733
|
+
ctx.lineTo(to.x, to.y);
|
|
734
|
+
ctx.stroke();
|
|
735
|
+
ctx.restore();
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
private handleCanvasAfterRender() {
|
|
739
|
+
if (!this.canvasService || !this.isImageEditingVisible()) {
|
|
740
|
+
return;
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
const frame = this.getFrameRect();
|
|
744
|
+
if (frame.width <= 0 || frame.height <= 0) {
|
|
745
|
+
return;
|
|
746
|
+
}
|
|
747
|
+
const frameScreen = this.getFrameRectScreen(frame);
|
|
748
|
+
let drew = false;
|
|
749
|
+
|
|
750
|
+
if (this.activeSnapX) {
|
|
751
|
+
const x = this.canvasService.toScreenPoint({
|
|
752
|
+
x: this.activeSnapX.lineScene,
|
|
753
|
+
y: frame.top,
|
|
754
|
+
}).x;
|
|
755
|
+
this.drawSnapGuideLine(
|
|
756
|
+
{ x, y: frameScreen.top },
|
|
757
|
+
{ x, y: frameScreen.top + frameScreen.height },
|
|
758
|
+
);
|
|
759
|
+
drew = true;
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
if (this.activeSnapY) {
|
|
763
|
+
const y = this.canvasService.toScreenPoint({
|
|
764
|
+
x: frame.left,
|
|
765
|
+
y: this.activeSnapY.lineScene,
|
|
766
|
+
}).y;
|
|
767
|
+
this.drawSnapGuideLine(
|
|
768
|
+
{ x: frameScreen.left, y },
|
|
769
|
+
{ x: frameScreen.left + frameScreen.width, y },
|
|
770
|
+
);
|
|
771
|
+
drew = true;
|
|
772
|
+
}
|
|
773
|
+
this.hasRenderedSnapGuides = drew;
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
private handleCanvasObjectMoving(e: any) {
|
|
777
|
+
const target = this.getActiveImageTarget(e?.target);
|
|
778
|
+
if (!target || !this.canvasService) return;
|
|
779
|
+
this.movingImageId =
|
|
780
|
+
typeof target?.data?.id === "string" ? target.data.id : null;
|
|
781
|
+
|
|
782
|
+
const frame = this.getFrameRect();
|
|
783
|
+
if (frame.width <= 0 || frame.height <= 0) {
|
|
784
|
+
this.endMoveSnapInteraction();
|
|
785
|
+
return;
|
|
786
|
+
}
|
|
787
|
+
const rawBounds = this.getTargetBoundsScene(target);
|
|
788
|
+
const matches = this.computeMoveSnapMatches(rawBounds, frame);
|
|
789
|
+
this.updateSnapMatchState(matches.x, matches.y);
|
|
790
|
+
}
|
|
791
|
+
|
|
415
792
|
private syncToolActiveFromWorkbench(fallbackId?: string | null) {
|
|
416
793
|
const wb = this.context?.services.get<WorkbenchService>("WorkbenchService");
|
|
417
794
|
const activeId = wb?.activeToolId;
|
|
@@ -1176,33 +1553,9 @@ export class ImageTool implements Extension {
|
|
|
1176
1553
|
originY: "top",
|
|
1177
1554
|
fill: hatchFill,
|
|
1178
1555
|
opacity: patternFill ? 1 : 0.8,
|
|
1179
|
-
stroke: null,
|
|
1180
|
-
fillRule: "evenodd",
|
|
1181
|
-
selectable: false,
|
|
1182
|
-
evented: false,
|
|
1183
|
-
excludeFromExport: true,
|
|
1184
|
-
objectCaching: false,
|
|
1185
|
-
},
|
|
1186
|
-
},
|
|
1187
|
-
{
|
|
1188
|
-
id: "image.cropShapePath",
|
|
1189
|
-
type: "path",
|
|
1190
|
-
data: { id: "image.cropShapePath", zIndex: 6 },
|
|
1191
|
-
layout: {
|
|
1192
|
-
reference: "custom",
|
|
1193
|
-
referenceRect: frameRect,
|
|
1194
|
-
alignX: "start",
|
|
1195
|
-
alignY: "start",
|
|
1196
|
-
offsetX: shapeBounds.x,
|
|
1197
|
-
offsetY: shapeBounds.y,
|
|
1198
|
-
},
|
|
1199
|
-
props: {
|
|
1200
|
-
pathData: shapePathData,
|
|
1201
|
-
originX: "left",
|
|
1202
|
-
originY: "top",
|
|
1203
|
-
fill: "rgba(0,0,0,0)",
|
|
1204
1556
|
stroke: "rgba(255, 0, 0, 0.9)",
|
|
1205
1557
|
strokeWidth: this.canvasService?.toSceneLength(1) ?? 1,
|
|
1558
|
+
fillRule: "evenodd",
|
|
1206
1559
|
selectable: false,
|
|
1207
1560
|
evented: false,
|
|
1208
1561
|
excludeFromExport: true,
|
|
@@ -1602,8 +1955,11 @@ export class ImageTool implements Extension {
|
|
|
1602
1955
|
const id = target?.data?.id;
|
|
1603
1956
|
const layerId = target?.data?.layerId;
|
|
1604
1957
|
if (typeof id !== "string" || layerId !== IMAGE_OBJECT_LAYER_ID) return;
|
|
1605
|
-
|
|
1958
|
+
if (this.movingImageId === id) {
|
|
1959
|
+
this.applyMoveSnapToTarget(target);
|
|
1960
|
+
}
|
|
1606
1961
|
const frame = this.getFrameRect();
|
|
1962
|
+
this.endMoveSnapInteraction();
|
|
1607
1963
|
if (!frame.width || !frame.height) return;
|
|
1608
1964
|
|
|
1609
1965
|
const center = target.getCenterPoint
|
|
@@ -5,6 +5,7 @@ export const WHITE_INK_OBJECT_LAYER_ID = "white-ink.user";
|
|
|
5
5
|
export const WHITE_INK_COVER_LAYER_ID = "white-ink.cover";
|
|
6
6
|
export const WHITE_INK_OVERLAY_LAYER_ID = "white-ink.overlay";
|
|
7
7
|
export const DIELINE_LAYER_ID = "dieline-overlay";
|
|
8
|
+
export const FEATURE_DIELINE_LAYER_ID = "feature-dieline-overlay";
|
|
8
9
|
export const FEATURE_OVERLAY_LAYER_ID = "feature-overlay";
|
|
9
10
|
export const RULER_LAYER_ID = "ruler-overlay";
|
|
10
11
|
export const FILM_LAYER_ID = "overlay";
|
|
@@ -17,6 +18,7 @@ export const LAYER_IDS = {
|
|
|
17
18
|
whiteInkCover: WHITE_INK_COVER_LAYER_ID,
|
|
18
19
|
whiteInkOverlay: WHITE_INK_OVERLAY_LAYER_ID,
|
|
19
20
|
dieline: DIELINE_LAYER_ID,
|
|
21
|
+
featureDieline: FEATURE_DIELINE_LAYER_ID,
|
|
20
22
|
featureOverlay: FEATURE_OVERLAY_LAYER_ID,
|
|
21
23
|
rulerOverlay: RULER_LAYER_ID,
|
|
22
24
|
filmOverlay: FILM_LAYER_ID,
|