@8btc/whiteboard 0.0.11 → 0.0.13
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/index.css +10 -4
- package/dist/index.d.ts +21 -1
- package/dist/index.js +218 -94
- package/dist/index.umd.js +228 -98
- package/package.json +1 -1
package/dist/index.css
CHANGED
|
@@ -54,6 +54,8 @@
|
|
|
54
54
|
--font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
|
55
55
|
--color-red-500: oklch(63.7% .237 25.331);
|
|
56
56
|
--color-red-600: oklch(57.7% .245 27.325);
|
|
57
|
+
--color-orange-500: oklch(70.5% .213 47.604);
|
|
58
|
+
--color-orange-600: oklch(64.6% .222 41.116);
|
|
57
59
|
--color-green-500: oklch(72.3% .219 149.579);
|
|
58
60
|
--color-green-600: oklch(62.7% .194 149.214);
|
|
59
61
|
--color-cyan-500: oklch(71.5% .143 215.221);
|
|
@@ -370,10 +372,6 @@
|
|
|
370
372
|
position: relative;
|
|
371
373
|
}
|
|
372
374
|
|
|
373
|
-
.static {
|
|
374
|
-
position: static;
|
|
375
|
-
}
|
|
376
|
-
|
|
377
375
|
.top-0 {
|
|
378
376
|
top: calc(var(--spacing) * 0);
|
|
379
377
|
}
|
|
@@ -643,6 +641,10 @@
|
|
|
643
641
|
background-color: var(--color-indigo-500);
|
|
644
642
|
}
|
|
645
643
|
|
|
644
|
+
.bg-orange-500 {
|
|
645
|
+
background-color: var(--color-orange-500);
|
|
646
|
+
}
|
|
647
|
+
|
|
646
648
|
.bg-primary {
|
|
647
649
|
background-color: var(--primary);
|
|
648
650
|
}
|
|
@@ -820,6 +822,10 @@
|
|
|
820
822
|
background-color: var(--color-indigo-600);
|
|
821
823
|
}
|
|
822
824
|
|
|
825
|
+
.hover\:bg-orange-600:hover {
|
|
826
|
+
background-color: var(--color-orange-600);
|
|
827
|
+
}
|
|
828
|
+
|
|
823
829
|
.hover\:bg-primary\/90:hover {
|
|
824
830
|
background-color: var(--primary);
|
|
825
831
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -19,6 +19,10 @@ export declare class CanvasApi extends CanvasCore {
|
|
|
19
19
|
* 如果你不知道自己在干什么,请使用更高层的封装方法,如 createImageNode
|
|
20
20
|
*/
|
|
21
21
|
createNodes(nodes: INode[]): void;
|
|
22
|
+
/**
|
|
23
|
+
* 根据 ID 获取节点
|
|
24
|
+
*/
|
|
25
|
+
getNodeById<T extends INode = INode>(id: string): T | null;
|
|
22
26
|
/**
|
|
23
27
|
* 更新视口位置
|
|
24
28
|
*/
|
|
@@ -51,6 +55,12 @@ export declare class CanvasApi extends CanvasCore {
|
|
|
51
55
|
quality?: number;
|
|
52
56
|
padding?: number;
|
|
53
57
|
}): string | null;
|
|
58
|
+
/**
|
|
59
|
+
* 导出带有标注的图片节点为图片
|
|
60
|
+
* @param id - 图片节点 ID
|
|
61
|
+
* @returns DataURL 格式的图片数据,如果节点不存在则返回 null
|
|
62
|
+
*/
|
|
63
|
+
exportImageWithMarker(id: string): string | null;
|
|
54
64
|
/**
|
|
55
65
|
* 删除当前选中的节点
|
|
56
66
|
* 如果删除的是 image 节点,会同步删除所有关联的 image-marker
|
|
@@ -147,6 +157,8 @@ declare class CanvasCore extends CanvasState_2 {
|
|
|
147
157
|
/* Excluded from this release type: updateDraftNode */
|
|
148
158
|
/* Excluded from this release type: finalizeDraftNode */
|
|
149
159
|
/* Excluded from this release type: selectNode */
|
|
160
|
+
/* Excluded from this release type: deleteNodes */
|
|
161
|
+
/* Excluded from this release type: deleteSelectedNodes */
|
|
150
162
|
/**
|
|
151
163
|
* 销毁 canvas
|
|
152
164
|
*/
|
|
@@ -357,7 +369,13 @@ declare interface IViewport {
|
|
|
357
369
|
scale: number;
|
|
358
370
|
}
|
|
359
371
|
|
|
360
|
-
export declare const
|
|
372
|
+
export declare const NODE_NAMES: {
|
|
373
|
+
nodeRoot: string;
|
|
374
|
+
selectable: string;
|
|
375
|
+
rect: string;
|
|
376
|
+
image: string;
|
|
377
|
+
imageMarker: string;
|
|
378
|
+
};
|
|
361
379
|
|
|
362
380
|
export declare type NodeType = "rectangle" | "image" | "image-marker";
|
|
363
381
|
|
|
@@ -384,10 +402,12 @@ declare type StateEvents = {
|
|
|
384
402
|
"state:redo": ICoreState;
|
|
385
403
|
"state:reset": ICoreState;
|
|
386
404
|
"viewport:change": ICoreState["viewport"];
|
|
405
|
+
"viewport:scale:change": number;
|
|
387
406
|
"transformer:positionChange": TransformerPosition | null;
|
|
388
407
|
"toolType:change": ICoreState["toolType"];
|
|
389
408
|
"nodes:created": ICoreState["nodes"];
|
|
390
409
|
"nodes:deleted": INode[];
|
|
410
|
+
"nodes:selected": string[];
|
|
391
411
|
};
|
|
392
412
|
|
|
393
413
|
export declare type ToolType = "select" | "hand" | "rectangle" | "image-marker";
|
package/dist/index.js
CHANGED
|
@@ -9,7 +9,7 @@ var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read fr
|
|
|
9
9
|
var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
10
10
|
var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
|
|
11
11
|
var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
|
|
12
|
-
var _core, _stage, _viewport, _handleWheel, _handlePointerDown, _handlePointerMove, _handlePointerUp, _handleDragStart, _handleDragMove, _handleDragEnd, _CanvasStage_instances, setupEventListeners_fn, _core2, _transformer, _handleTransformStart, _handleTransform, _handleTransformEnd, _handleDragStart2, _handleDragMove2, _handleDragEnd2, _CanvasTransformer_instances, setupEventListeners_fn2, _toolTypeChangeHandler, _RectNode_instances, setupEventHandlers_fn, _ImageNode_instances, loadImage_fn, _toolTypeChangeHandler2, setupEventHandlers_fn2, syncImageMarkers_fn, syncImageMarkersToState_fn, _rect, _markerGroup, _circle, _text, _ImageMarkerNode_instances, setupEventHandlers_fn3, _canvasStage, _mainLayer, _canvasTransformer, _draftNode;
|
|
12
|
+
var _core, _stage, _viewport, _handleWheel, _handlePointerDown, _handlePointerMove, _handlePointerUp, _handleDragStart, _handleDragMove, _handleDragEnd, _CanvasStage_instances, setupEventListeners_fn, _core2, _transformer, _handleTransformStart, _handleTransform, _handleTransformEnd, _handleDragStart2, _handleDragMove2, _handleDragEnd2, _CanvasTransformer_instances, setupEventListeners_fn2, _toolTypeChangeHandler, _RectNode_instances, setupEventHandlers_fn, _ImageNode_instances, loadImage_fn, _toolTypeChangeHandler2, setupEventHandlers_fn2, syncImageMarkers_fn, syncImageMarkersToState_fn, _rect, _markerGroup, _circle, _text, _handleViewportChange, _handleNodesSelected, _ImageMarkerNode_instances, updateMarkerScale_fn, setupEventHandlers_fn3, _canvasStage, _mainLayer, _canvasTransformer, _draftNode, _container, _handleKeyDown, _CanvasCore_instances, setupKeyboardEvents_fn;
|
|
13
13
|
import { jsxs, jsx, Fragment } from "react/jsx-runtime";
|
|
14
14
|
import { useState, useEffect, useRef } from "react";
|
|
15
15
|
import Konva from "konva";
|
|
@@ -509,7 +509,13 @@ class CanvasState {
|
|
|
509
509
|
this._emitter.all.clear();
|
|
510
510
|
}
|
|
511
511
|
}
|
|
512
|
-
const
|
|
512
|
+
const NODE_NAMES = {
|
|
513
|
+
nodeRoot: "nodeRoot_intrinsic",
|
|
514
|
+
selectable: "selectable_intrinsic",
|
|
515
|
+
rect: "rect_intrinsic",
|
|
516
|
+
image: "image_intrinsic",
|
|
517
|
+
imageMarker: "image_marker_intrinsic"
|
|
518
|
+
};
|
|
513
519
|
const RECT = {
|
|
514
520
|
CORNER_RADIUS: 6,
|
|
515
521
|
MIN_SIZE: 10
|
|
@@ -573,7 +579,7 @@ class RectNode extends BaseCanvasNode {
|
|
|
573
579
|
width,
|
|
574
580
|
height,
|
|
575
581
|
cornerRadius: RECT.CORNER_RADIUS,
|
|
576
|
-
name:
|
|
582
|
+
name: `${NODE_NAMES.nodeRoot} ${NODE_NAMES.selectable} ${NODE_NAMES.rect}`,
|
|
577
583
|
draggable: true,
|
|
578
584
|
stroke: "black",
|
|
579
585
|
strokeWidth: 2
|
|
@@ -692,7 +698,7 @@ class ImageNode extends BaseCanvasNode {
|
|
|
692
698
|
id: this.node.id,
|
|
693
699
|
x: this.node.props.x,
|
|
694
700
|
y: this.node.props.y,
|
|
695
|
-
name:
|
|
701
|
+
name: `${NODE_NAMES.nodeRoot} ${NODE_NAMES.selectable} ${NODE_NAMES.image}`,
|
|
696
702
|
draggable: true,
|
|
697
703
|
image: placeholder
|
|
698
704
|
});
|
|
@@ -889,12 +895,23 @@ class ImageMarkerNode extends BaseCanvasNode {
|
|
|
889
895
|
__privateAdd(this, _markerGroup);
|
|
890
896
|
__privateAdd(this, _circle);
|
|
891
897
|
__privateAdd(this, _text);
|
|
898
|
+
__privateAdd(this, _handleViewportChange);
|
|
899
|
+
__privateAdd(this, _handleNodesSelected);
|
|
892
900
|
const group = this.getElement();
|
|
893
901
|
__privateSet(this, _rect, group.findOne(".rect"));
|
|
894
902
|
__privateSet(this, _markerGroup, group.findOne(".marker-group"));
|
|
895
903
|
__privateSet(this, _circle, __privateGet(this, _markerGroup).findOne("Circle"));
|
|
896
904
|
__privateSet(this, _text, __privateGet(this, _markerGroup).findOne("Text"));
|
|
897
905
|
__privateMethod(this, _ImageMarkerNode_instances, setupEventHandlers_fn3).call(this);
|
|
906
|
+
__privateSet(this, _handleViewportChange, () => {
|
|
907
|
+
__privateMethod(this, _ImageMarkerNode_instances, updateMarkerScale_fn).call(this);
|
|
908
|
+
});
|
|
909
|
+
this.core.on("viewport:scale:change", __privateGet(this, _handleViewportChange));
|
|
910
|
+
__privateSet(this, _handleNodesSelected, (selectedIds) => {
|
|
911
|
+
const isSelected = selectedIds.includes(this.node.id);
|
|
912
|
+
this.setFocusState(isSelected);
|
|
913
|
+
});
|
|
914
|
+
this.core.on("nodes:selected", __privateGet(this, _handleNodesSelected));
|
|
898
915
|
}
|
|
899
916
|
createElement() {
|
|
900
917
|
const width = Math.max(
|
|
@@ -907,23 +924,27 @@ class ImageMarkerNode extends BaseCanvasNode {
|
|
|
907
924
|
);
|
|
908
925
|
const group = new Konva.Group({
|
|
909
926
|
id: this.node.id,
|
|
910
|
-
name:
|
|
927
|
+
name: `${NODE_NAMES.nodeRoot} ${NODE_NAMES.imageMarker} ${this.node.meta.parent} ${NODE_NAMES.selectable}`,
|
|
911
928
|
x: this.node.props.x,
|
|
912
929
|
y: this.node.props.y,
|
|
913
930
|
width,
|
|
914
931
|
height
|
|
915
932
|
});
|
|
933
|
+
const stageScale = this.core.getStageScale();
|
|
934
|
+
const rectStrokeWidth = 2 / stageScale;
|
|
935
|
+
const rectDash = [5 / stageScale, 5 / stageScale];
|
|
936
|
+
const rectCornerRadius = RECT.CORNER_RADIUS / stageScale;
|
|
916
937
|
const rect = new Konva.Rect({
|
|
917
938
|
name: "rect",
|
|
918
939
|
x: 0,
|
|
919
940
|
y: 0,
|
|
920
941
|
width,
|
|
921
942
|
height,
|
|
922
|
-
stroke:
|
|
923
|
-
strokeWidth:
|
|
924
|
-
dash:
|
|
943
|
+
stroke: "#3B82F6",
|
|
944
|
+
strokeWidth: rectStrokeWidth,
|
|
945
|
+
dash: rectDash,
|
|
925
946
|
fill: "transparent",
|
|
926
|
-
cornerRadius:
|
|
947
|
+
cornerRadius: rectCornerRadius,
|
|
927
948
|
listening: false
|
|
928
949
|
});
|
|
929
950
|
const markerGroup = new Konva.Group({
|
|
@@ -932,13 +953,14 @@ class ImageMarkerNode extends BaseCanvasNode {
|
|
|
932
953
|
y: height,
|
|
933
954
|
visible: this.isDraft ? false : true
|
|
934
955
|
});
|
|
935
|
-
const
|
|
936
|
-
const
|
|
956
|
+
const radius = 14 / stageScale;
|
|
957
|
+
const strokeWidth = 3 / stageScale;
|
|
958
|
+
const fontSize = 16 / stageScale;
|
|
937
959
|
const circle = new Konva.Circle({
|
|
938
960
|
radius,
|
|
939
|
-
fill: "
|
|
940
|
-
stroke: "
|
|
941
|
-
strokeWidth
|
|
961
|
+
fill: "#3B82F6",
|
|
962
|
+
stroke: "white",
|
|
963
|
+
strokeWidth
|
|
942
964
|
});
|
|
943
965
|
const text = new Konva.Text({
|
|
944
966
|
x: -radius,
|
|
@@ -948,7 +970,7 @@ class ImageMarkerNode extends BaseCanvasNode {
|
|
|
948
970
|
text: String(this.node.meta.markerNumber || ""),
|
|
949
971
|
align: "center",
|
|
950
972
|
verticalAlign: "middle",
|
|
951
|
-
fontSize
|
|
973
|
+
fontSize,
|
|
952
974
|
fill: "white"
|
|
953
975
|
});
|
|
954
976
|
markerGroup.add(circle);
|
|
@@ -1011,13 +1033,15 @@ class ImageMarkerNode extends BaseCanvasNode {
|
|
|
1011
1033
|
* 销毁
|
|
1012
1034
|
*/
|
|
1013
1035
|
destroy() {
|
|
1036
|
+
this.core.off("viewport:scale:change", __privateGet(this, _handleViewportChange));
|
|
1037
|
+
this.core.off("nodes:selected", __privateGet(this, _handleNodesSelected));
|
|
1014
1038
|
this.element.destroy();
|
|
1015
1039
|
}
|
|
1016
1040
|
/**
|
|
1017
1041
|
* 更新焦点状态(hover 或 selected)
|
|
1018
1042
|
*/
|
|
1019
1043
|
setFocusState(isFocus) {
|
|
1020
|
-
const strokeWidth = isFocus ? 4 :
|
|
1044
|
+
const strokeWidth = isFocus ? 4 : 3;
|
|
1021
1045
|
const scale = isFocus ? 1.2 : 1;
|
|
1022
1046
|
__privateGet(this, _rect).strokeWidth(strokeWidth);
|
|
1023
1047
|
__privateGet(this, _circle).strokeWidth(strokeWidth);
|
|
@@ -1029,7 +1053,31 @@ _rect = new WeakMap();
|
|
|
1029
1053
|
_markerGroup = new WeakMap();
|
|
1030
1054
|
_circle = new WeakMap();
|
|
1031
1055
|
_text = new WeakMap();
|
|
1056
|
+
_handleViewportChange = new WeakMap();
|
|
1057
|
+
_handleNodesSelected = new WeakMap();
|
|
1032
1058
|
_ImageMarkerNode_instances = new WeakSet();
|
|
1059
|
+
/**
|
|
1060
|
+
* 更新标记点的缩放以保持视觉大小不变
|
|
1061
|
+
*/
|
|
1062
|
+
updateMarkerScale_fn = function() {
|
|
1063
|
+
const stageScale = this.core.getStageScale();
|
|
1064
|
+
const radius = 14 / stageScale;
|
|
1065
|
+
const strokeWidth = 3 / stageScale;
|
|
1066
|
+
const fontSize = 16 / stageScale;
|
|
1067
|
+
const rectStrokeWidth = 3 / stageScale;
|
|
1068
|
+
const rectDash = [5 / stageScale, 5 / stageScale];
|
|
1069
|
+
const rectCornerRadius = RECT.CORNER_RADIUS / stageScale;
|
|
1070
|
+
__privateGet(this, _rect).strokeWidth(rectStrokeWidth);
|
|
1071
|
+
__privateGet(this, _rect).dash(rectDash);
|
|
1072
|
+
__privateGet(this, _rect).cornerRadius(rectCornerRadius);
|
|
1073
|
+
__privateGet(this, _circle).radius(radius);
|
|
1074
|
+
__privateGet(this, _circle).strokeWidth(strokeWidth);
|
|
1075
|
+
__privateGet(this, _text).x(-radius);
|
|
1076
|
+
__privateGet(this, _text).y(-radius);
|
|
1077
|
+
__privateGet(this, _text).width(radius * 2);
|
|
1078
|
+
__privateGet(this, _text).height(radius * 2);
|
|
1079
|
+
__privateGet(this, _text).fontSize(fontSize);
|
|
1080
|
+
};
|
|
1033
1081
|
/**
|
|
1034
1082
|
* 设置事件处理器
|
|
1035
1083
|
*/
|
|
@@ -1091,8 +1139,7 @@ const createNodeByType = (type, position, style, meta) => {
|
|
|
1091
1139
|
...baseNode,
|
|
1092
1140
|
style: {
|
|
1093
1141
|
...baseNode.style,
|
|
1094
|
-
color: "#
|
|
1095
|
-
line: "dashed"
|
|
1142
|
+
color: "#3B82F6"
|
|
1096
1143
|
}
|
|
1097
1144
|
};
|
|
1098
1145
|
}
|
|
@@ -1161,10 +1208,19 @@ class CanvasCore extends CanvasState {
|
|
|
1161
1208
|
toolType: "select",
|
|
1162
1209
|
nodes: []
|
|
1163
1210
|
});
|
|
1211
|
+
__privateAdd(this, _CanvasCore_instances);
|
|
1164
1212
|
__privateAdd(this, _canvasStage);
|
|
1165
1213
|
__privateAdd(this, _mainLayer);
|
|
1166
1214
|
__privateAdd(this, _canvasTransformer);
|
|
1167
1215
|
__privateAdd(this, _draftNode, null);
|
|
1216
|
+
__privateAdd(this, _container);
|
|
1217
|
+
__privateAdd(this, _handleKeyDown, (e) => {
|
|
1218
|
+
if (e.key === "Delete" || e.key === "Backspace") {
|
|
1219
|
+
e.preventDefault();
|
|
1220
|
+
this.deleteSelectedNodes();
|
|
1221
|
+
}
|
|
1222
|
+
});
|
|
1223
|
+
__privateSet(this, _container, el);
|
|
1168
1224
|
__privateSet(this, _canvasStage, new CanvasStage(this, {
|
|
1169
1225
|
container: el,
|
|
1170
1226
|
width: el.clientWidth,
|
|
@@ -1177,6 +1233,7 @@ class CanvasCore extends CanvasState {
|
|
|
1177
1233
|
__privateGet(this, _canvasStage).getStage().add(__privateGet(this, _mainLayer));
|
|
1178
1234
|
__privateGet(this, _mainLayer).add(__privateGet(this, _canvasTransformer).getTransformer());
|
|
1179
1235
|
this.updateViewport(this.getState().viewport, false);
|
|
1236
|
+
__privateMethod(this, _CanvasCore_instances, setupKeyboardEvents_fn).call(this);
|
|
1180
1237
|
}
|
|
1181
1238
|
/**
|
|
1182
1239
|
* 获取 CanvasStage 实例
|
|
@@ -1272,8 +1329,9 @@ class CanvasCore extends CanvasState {
|
|
|
1272
1329
|
*/
|
|
1273
1330
|
updateViewport(viewport, addToHistory = false) {
|
|
1274
1331
|
__privateGet(this, _canvasStage).setViewport(viewport);
|
|
1332
|
+
const oldViewport = this.getState().viewport;
|
|
1275
1333
|
const newViewport = {
|
|
1276
|
-
...
|
|
1334
|
+
...oldViewport,
|
|
1277
1335
|
...viewport
|
|
1278
1336
|
};
|
|
1279
1337
|
this._updateState(
|
|
@@ -1283,6 +1341,9 @@ class CanvasCore extends CanvasState {
|
|
|
1283
1341
|
addToHistory
|
|
1284
1342
|
);
|
|
1285
1343
|
this.emit("viewport:change", newViewport);
|
|
1344
|
+
if (oldViewport.scale !== newViewport.scale) {
|
|
1345
|
+
this.emit("viewport:scale:change", newViewport.scale);
|
|
1346
|
+
}
|
|
1286
1347
|
__privateGet(this, _canvasTransformer).emitPositionChange();
|
|
1287
1348
|
}
|
|
1288
1349
|
createNodes(nodes) {
|
|
@@ -1330,7 +1391,7 @@ class CanvasCore extends CanvasState {
|
|
|
1330
1391
|
visible: true
|
|
1331
1392
|
},
|
|
1332
1393
|
style: {
|
|
1333
|
-
color: "#
|
|
1394
|
+
color: "#3B82F6",
|
|
1334
1395
|
line: "dashed",
|
|
1335
1396
|
size: "medium",
|
|
1336
1397
|
opacity: 1
|
|
@@ -1478,41 +1539,79 @@ class CanvasCore extends CanvasState {
|
|
|
1478
1539
|
*/
|
|
1479
1540
|
selectNode(nodeId, multiSelect = false) {
|
|
1480
1541
|
const curSelectedNodeIds = this.getState().selectedNodeIds ?? [];
|
|
1481
|
-
|
|
1542
|
+
let selectedNodeIds = [];
|
|
1543
|
+
if (nodeId) {
|
|
1544
|
+
if (multiSelect && curSelectedNodeIds.length > 0) {
|
|
1545
|
+
selectedNodeIds = [...curSelectedNodeIds, nodeId];
|
|
1546
|
+
} else {
|
|
1547
|
+
selectedNodeIds = [nodeId];
|
|
1548
|
+
}
|
|
1549
|
+
} else if (curSelectedNodeIds.length === 0) {
|
|
1482
1550
|
return;
|
|
1483
1551
|
}
|
|
1484
|
-
if (
|
|
1552
|
+
if (selectedNodeIds.length === 0) {
|
|
1485
1553
|
__privateGet(this, _canvasTransformer).clearNodes();
|
|
1486
|
-
this._updateState(
|
|
1487
|
-
{
|
|
1488
|
-
selectedNodeIds: []
|
|
1489
|
-
},
|
|
1490
|
-
false
|
|
1491
|
-
);
|
|
1492
|
-
return;
|
|
1493
|
-
}
|
|
1494
|
-
let selectedNodeIds = [];
|
|
1495
|
-
if (multiSelect) {
|
|
1496
|
-
selectedNodeIds = curSelectedNodeIds.length ? [...curSelectedNodeIds, nodeId] : [nodeId];
|
|
1497
1554
|
} else {
|
|
1498
|
-
|
|
1555
|
+
const nodes = this.getStage().find(`.${NODE_NAMES.selectable}`).filter((node) => selectedNodeIds.includes(node.id()));
|
|
1556
|
+
__privateGet(this, _canvasTransformer).setNodes(nodes);
|
|
1499
1557
|
}
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1558
|
+
this._updateState({ selectedNodeIds }, false);
|
|
1559
|
+
this.emit("nodes:selected", selectedNodeIds);
|
|
1560
|
+
}
|
|
1561
|
+
/**
|
|
1562
|
+
* 删除指定的节点(内部使用)
|
|
1563
|
+
* 如果删除的是 image 节点,会同步删除所有关联的 image-marker
|
|
1564
|
+
* @internal 仅供内部使用,外部请使用 CanvasApi
|
|
1565
|
+
* @param nodeIds - 要删除的节点 ID 数组
|
|
1566
|
+
* @returns 被删除的节点数据数组
|
|
1567
|
+
*/
|
|
1568
|
+
deleteNodes(nodeIds) {
|
|
1569
|
+
if (nodeIds.length === 0) return [];
|
|
1570
|
+
const nodes = this.getState().nodes || [];
|
|
1571
|
+
const idsToDelete = new Set(nodeIds);
|
|
1572
|
+
nodeIds.forEach((id) => {
|
|
1573
|
+
const node = nodes.find((n) => n.id === id);
|
|
1574
|
+
if (node?.type === "image") {
|
|
1575
|
+
nodes.forEach((n) => {
|
|
1576
|
+
if (n.type === "image-marker" && n.meta.parent === id) {
|
|
1577
|
+
idsToDelete.add(n.id);
|
|
1578
|
+
}
|
|
1579
|
+
});
|
|
1580
|
+
}
|
|
1503
1581
|
});
|
|
1504
|
-
|
|
1582
|
+
const deletedNodes = nodes.filter((n) => idsToDelete.has(n.id));
|
|
1583
|
+
idsToDelete.forEach((id) => {
|
|
1584
|
+
const shape = this.getStage().findOne(`#${id}`);
|
|
1585
|
+
if (shape) {
|
|
1586
|
+
shape.destroy();
|
|
1587
|
+
}
|
|
1588
|
+
});
|
|
1589
|
+
const newNodes = nodes.filter((n) => !idsToDelete.has(n.id));
|
|
1590
|
+
__privateGet(this, _canvasTransformer).clearNodes();
|
|
1505
1591
|
this._updateState(
|
|
1506
1592
|
{
|
|
1507
|
-
|
|
1593
|
+
nodes: newNodes,
|
|
1594
|
+
selectedNodeIds: []
|
|
1508
1595
|
},
|
|
1509
|
-
|
|
1596
|
+
true
|
|
1510
1597
|
);
|
|
1598
|
+
this.emit("nodes:deleted", deletedNodes);
|
|
1599
|
+
return deletedNodes;
|
|
1600
|
+
}
|
|
1601
|
+
/**
|
|
1602
|
+
* 删除选中的节点(内部使用)
|
|
1603
|
+
* @internal 仅供内部使用,外部请使用 CanvasApi
|
|
1604
|
+
*/
|
|
1605
|
+
deleteSelectedNodes() {
|
|
1606
|
+
const selectedNodeIds = this.getState().selectedNodeIds || [];
|
|
1607
|
+
if (selectedNodeIds.length === 0) return;
|
|
1608
|
+
this.deleteNodes(selectedNodeIds);
|
|
1511
1609
|
}
|
|
1512
1610
|
/**
|
|
1513
1611
|
* 销毁 canvas
|
|
1514
1612
|
*/
|
|
1515
1613
|
dispose() {
|
|
1614
|
+
__privateGet(this, _container).removeEventListener("keydown", __privateGet(this, _handleKeyDown));
|
|
1516
1615
|
this.getCanvasTransformer().destroy();
|
|
1517
1616
|
this.getMainLayer().destroy();
|
|
1518
1617
|
this.getCanvasStage().destroy();
|
|
@@ -1568,6 +1667,16 @@ _canvasStage = new WeakMap();
|
|
|
1568
1667
|
_mainLayer = new WeakMap();
|
|
1569
1668
|
_canvasTransformer = new WeakMap();
|
|
1570
1669
|
_draftNode = new WeakMap();
|
|
1670
|
+
_container = new WeakMap();
|
|
1671
|
+
_handleKeyDown = new WeakMap();
|
|
1672
|
+
_CanvasCore_instances = new WeakSet();
|
|
1673
|
+
/**
|
|
1674
|
+
* 设置键盘事件监听
|
|
1675
|
+
*/
|
|
1676
|
+
setupKeyboardEvents_fn = function() {
|
|
1677
|
+
__privateGet(this, _container).tabIndex = 0;
|
|
1678
|
+
__privateGet(this, _container).addEventListener("keydown", __privateGet(this, _handleKeyDown));
|
|
1679
|
+
};
|
|
1571
1680
|
class CanvasApi extends CanvasCore {
|
|
1572
1681
|
/**
|
|
1573
1682
|
* 获取所有可用的工具类型
|
|
@@ -1588,6 +1697,14 @@ class CanvasApi extends CanvasCore {
|
|
|
1588
1697
|
createNodes(nodes) {
|
|
1589
1698
|
super.createNodes(nodes);
|
|
1590
1699
|
}
|
|
1700
|
+
/**
|
|
1701
|
+
* 根据 ID 获取节点
|
|
1702
|
+
*/
|
|
1703
|
+
getNodeById(id) {
|
|
1704
|
+
const nodes = this.getState().nodes || [];
|
|
1705
|
+
const node = nodes.find((n) => n.id === id);
|
|
1706
|
+
return node || null;
|
|
1707
|
+
}
|
|
1591
1708
|
/**
|
|
1592
1709
|
* 更新视口位置
|
|
1593
1710
|
*/
|
|
@@ -1648,38 +1765,75 @@ class CanvasApi extends CanvasCore {
|
|
|
1648
1765
|
* @returns DataURL 格式的图片数据,如果没有选区则返回 null
|
|
1649
1766
|
*/
|
|
1650
1767
|
exportSelectionAsImage(options) {
|
|
1651
|
-
const
|
|
1652
|
-
if (
|
|
1768
|
+
const selectedNodeIds = this.getState().selectedNodeIds || [];
|
|
1769
|
+
if (selectedNodeIds.length === 0) {
|
|
1653
1770
|
console.warn("No selection to export");
|
|
1654
1771
|
return null;
|
|
1655
1772
|
}
|
|
1656
|
-
const stage = this.getStage();
|
|
1657
1773
|
const padding = options?.padding ?? 0;
|
|
1658
|
-
const
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1774
|
+
const tempGroup = new Konva.Group();
|
|
1775
|
+
selectedNodeIds.forEach((id) => {
|
|
1776
|
+
const shape = this.getStage().findOne(`#${id}`);
|
|
1777
|
+
if (shape) {
|
|
1778
|
+
const clone = shape.clone();
|
|
1779
|
+
tempGroup.add(clone);
|
|
1780
|
+
}
|
|
1781
|
+
});
|
|
1782
|
+
const box = tempGroup.getClientRect();
|
|
1783
|
+
const dataURL = tempGroup.toDataURL({
|
|
1784
|
+
x: box.x - padding,
|
|
1785
|
+
y: box.y - padding,
|
|
1786
|
+
width: box.width + padding * 2,
|
|
1787
|
+
height: box.height + padding * 2,
|
|
1788
|
+
pixelRatio: options?.pixelRatio ?? 2,
|
|
1789
|
+
mimeType: options?.mimeType ?? "image/png",
|
|
1790
|
+
quality: options?.quality ?? 1
|
|
1791
|
+
});
|
|
1792
|
+
tempGroup.destroy();
|
|
1793
|
+
return dataURL;
|
|
1794
|
+
}
|
|
1795
|
+
/**
|
|
1796
|
+
* 导出带有标注的图片节点为图片
|
|
1797
|
+
* @param id - 图片节点 ID
|
|
1798
|
+
* @returns DataURL 格式的图片数据,如果节点不存在则返回 null
|
|
1799
|
+
*/
|
|
1800
|
+
exportImageWithMarker(id) {
|
|
1801
|
+
const imageShape = this.getStage().findOne(`#${id}`);
|
|
1802
|
+
if (!imageShape) {
|
|
1803
|
+
console.warn("Image shape not found on stage");
|
|
1804
|
+
return null;
|
|
1673
1805
|
}
|
|
1806
|
+
const nodes = this.getState().nodes || [];
|
|
1807
|
+
const markerNodes = nodes.filter(
|
|
1808
|
+
(n) => n.type === "image-marker" && n.meta.parent === id
|
|
1809
|
+
);
|
|
1810
|
+
const tempGroup = new Konva.Group();
|
|
1811
|
+
const imageClone = imageShape.clone();
|
|
1812
|
+
tempGroup.add(imageClone);
|
|
1813
|
+
markerNodes.forEach((markerNode) => {
|
|
1814
|
+
const markerShape = this.getStage().findOne(`#${markerNode.id}`);
|
|
1815
|
+
if (markerShape) {
|
|
1816
|
+
const markerClone = markerShape.clone();
|
|
1817
|
+
tempGroup.add(markerClone);
|
|
1818
|
+
}
|
|
1819
|
+
});
|
|
1820
|
+
const box = tempGroup.getClientRect();
|
|
1821
|
+
const dataURL = tempGroup.toDataURL({
|
|
1822
|
+
x: box.x,
|
|
1823
|
+
y: box.y,
|
|
1824
|
+
width: box.width,
|
|
1825
|
+
height: box.height,
|
|
1826
|
+
pixelRatio: 2
|
|
1827
|
+
});
|
|
1828
|
+
tempGroup.destroy();
|
|
1829
|
+
return dataURL;
|
|
1674
1830
|
}
|
|
1675
1831
|
/**
|
|
1676
1832
|
* 删除当前选中的节点
|
|
1677
1833
|
* 如果删除的是 image 节点,会同步删除所有关联的 image-marker
|
|
1678
1834
|
*/
|
|
1679
1835
|
deleteSelectedNodes() {
|
|
1680
|
-
|
|
1681
|
-
if (selectedNodeIds.length === 0) return;
|
|
1682
|
-
this.deleteNodes(selectedNodeIds);
|
|
1836
|
+
super.deleteSelectedNodes();
|
|
1683
1837
|
}
|
|
1684
1838
|
/**
|
|
1685
1839
|
* 删除指定的节点
|
|
@@ -1688,37 +1842,7 @@ class CanvasApi extends CanvasCore {
|
|
|
1688
1842
|
* @returns 被删除的节点数据数组
|
|
1689
1843
|
*/
|
|
1690
1844
|
deleteNodes(nodeIds) {
|
|
1691
|
-
|
|
1692
|
-
const nodes = this.getState().nodes || [];
|
|
1693
|
-
const idsToDelete = new Set(nodeIds);
|
|
1694
|
-
nodeIds.forEach((id) => {
|
|
1695
|
-
const node = nodes.find((n) => n.id === id);
|
|
1696
|
-
if (node?.type === "image") {
|
|
1697
|
-
nodes.forEach((n) => {
|
|
1698
|
-
if (n.type === "image-marker" && n.meta.parent === id) {
|
|
1699
|
-
idsToDelete.add(n.id);
|
|
1700
|
-
}
|
|
1701
|
-
});
|
|
1702
|
-
}
|
|
1703
|
-
});
|
|
1704
|
-
const deletedNodes = nodes.filter((n) => idsToDelete.has(n.id));
|
|
1705
|
-
idsToDelete.forEach((id) => {
|
|
1706
|
-
const shape = this.getStage().findOne(`#${id}`);
|
|
1707
|
-
if (shape) {
|
|
1708
|
-
shape.destroy();
|
|
1709
|
-
}
|
|
1710
|
-
});
|
|
1711
|
-
const newNodes = nodes.filter((n) => !idsToDelete.has(n.id));
|
|
1712
|
-
this.getCanvasTransformer().clearNodes();
|
|
1713
|
-
this._updateState(
|
|
1714
|
-
{
|
|
1715
|
-
nodes: newNodes,
|
|
1716
|
-
selectedNodeIds: []
|
|
1717
|
-
},
|
|
1718
|
-
true
|
|
1719
|
-
);
|
|
1720
|
-
this.emit("nodes:deleted", deletedNodes);
|
|
1721
|
-
return deletedNodes;
|
|
1845
|
+
return super.deleteNodes(nodeIds);
|
|
1722
1846
|
}
|
|
1723
1847
|
/**
|
|
1724
1848
|
* 滚动到内容区域
|
|
@@ -1746,7 +1870,7 @@ class CanvasApi extends CanvasCore {
|
|
|
1746
1870
|
const hasSelection = !hasTargetIds && selectedNodeIds.length > 0;
|
|
1747
1871
|
const idsToShow = hasTargetIds ? targetNodeIds : hasSelection ? selectedNodeIds : null;
|
|
1748
1872
|
mainLayer.children.forEach((child) => {
|
|
1749
|
-
if (child.visible() && child.getClassName() !== "Transformer" && child.hasName(
|
|
1873
|
+
if (child.visible() && child.getClassName() !== "Transformer" && child.hasName(NODE_NAMES.selectable)) {
|
|
1750
1874
|
if (idsToShow) {
|
|
1751
1875
|
const id = child.id();
|
|
1752
1876
|
if (!idsToShow.includes(id)) return;
|
|
@@ -2064,6 +2188,6 @@ function PureCanvas({ setApi }) {
|
|
|
2064
2188
|
}
|
|
2065
2189
|
export {
|
|
2066
2190
|
CanvasApi,
|
|
2067
|
-
|
|
2191
|
+
NODE_NAMES,
|
|
2068
2192
|
PureCanvas
|
|
2069
2193
|
};
|
package/dist/index.umd.js
CHANGED
|
@@ -13,7 +13,7 @@ var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot
|
|
|
13
13
|
var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
|
|
14
14
|
var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
|
|
15
15
|
|
|
16
|
-
var _core, _stage, _viewport, _handleWheel, _handlePointerDown, _handlePointerMove, _handlePointerUp, _handleDragStart, _handleDragMove, _handleDragEnd, _CanvasStage_instances, setupEventListeners_fn, _core2, _transformer, _handleTransformStart, _handleTransform, _handleTransformEnd, _handleDragStart2, _handleDragMove2, _handleDragEnd2, _CanvasTransformer_instances, setupEventListeners_fn2, _toolTypeChangeHandler, _RectNode_instances, setupEventHandlers_fn, _ImageNode_instances, loadImage_fn, _toolTypeChangeHandler2, setupEventHandlers_fn2, syncImageMarkers_fn, syncImageMarkersToState_fn, _rect, _markerGroup, _circle, _text, _ImageMarkerNode_instances, setupEventHandlers_fn3, _canvasStage, _mainLayer, _canvasTransformer, _draftNode;
|
|
16
|
+
var _core, _stage, _viewport, _handleWheel, _handlePointerDown, _handlePointerMove, _handlePointerUp, _handleDragStart, _handleDragMove, _handleDragEnd, _CanvasStage_instances, setupEventListeners_fn, _core2, _transformer, _handleTransformStart, _handleTransform, _handleTransformEnd, _handleDragStart2, _handleDragMove2, _handleDragEnd2, _CanvasTransformer_instances, setupEventListeners_fn2, _toolTypeChangeHandler, _RectNode_instances, setupEventHandlers_fn, _ImageNode_instances, loadImage_fn, _toolTypeChangeHandler2, setupEventHandlers_fn2, syncImageMarkers_fn, syncImageMarkersToState_fn, _rect, _markerGroup, _circle, _text, _handleViewportChange, _handleNodesSelected, _ImageMarkerNode_instances, updateMarkerScale_fn, setupEventHandlers_fn3, _canvasStage, _mainLayer, _canvasTransformer, _draftNode, _container, _handleKeyDown, _CanvasCore_instances, setupKeyboardEvents_fn;
|
|
17
17
|
var __vite_style__ = document.createElement("style");
|
|
18
18
|
__vite_style__.textContent = `/*! tailwindcss v4.1.18 | MIT License | https://tailwindcss.com */
|
|
19
19
|
@layer properties {
|
|
@@ -71,6 +71,8 @@ var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "acce
|
|
|
71
71
|
--font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
|
72
72
|
--color-red-500: oklch(63.7% .237 25.331);
|
|
73
73
|
--color-red-600: oklch(57.7% .245 27.325);
|
|
74
|
+
--color-orange-500: oklch(70.5% .213 47.604);
|
|
75
|
+
--color-orange-600: oklch(64.6% .222 41.116);
|
|
74
76
|
--color-green-500: oklch(72.3% .219 149.579);
|
|
75
77
|
--color-green-600: oklch(62.7% .194 149.214);
|
|
76
78
|
--color-cyan-500: oklch(71.5% .143 215.221);
|
|
@@ -387,10 +389,6 @@ var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "acce
|
|
|
387
389
|
position: relative;
|
|
388
390
|
}
|
|
389
391
|
|
|
390
|
-
.static {
|
|
391
|
-
position: static;
|
|
392
|
-
}
|
|
393
|
-
|
|
394
392
|
.top-0 {
|
|
395
393
|
top: calc(var(--spacing) * 0);
|
|
396
394
|
}
|
|
@@ -660,6 +658,10 @@ var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "acce
|
|
|
660
658
|
background-color: var(--color-indigo-500);
|
|
661
659
|
}
|
|
662
660
|
|
|
661
|
+
.bg-orange-500 {
|
|
662
|
+
background-color: var(--color-orange-500);
|
|
663
|
+
}
|
|
664
|
+
|
|
663
665
|
.bg-primary {
|
|
664
666
|
background-color: var(--primary);
|
|
665
667
|
}
|
|
@@ -837,6 +839,10 @@ var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "acce
|
|
|
837
839
|
background-color: var(--color-indigo-600);
|
|
838
840
|
}
|
|
839
841
|
|
|
842
|
+
.hover\\:bg-orange-600:hover {
|
|
843
|
+
background-color: var(--color-orange-600);
|
|
844
|
+
}
|
|
845
|
+
|
|
840
846
|
.hover\\:bg-primary\\/90:hover {
|
|
841
847
|
background-color: var(--primary);
|
|
842
848
|
}
|
|
@@ -1820,7 +1826,13 @@ var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "acce
|
|
|
1820
1826
|
this._emitter.all.clear();
|
|
1821
1827
|
}
|
|
1822
1828
|
}
|
|
1823
|
-
const
|
|
1829
|
+
const NODE_NAMES = {
|
|
1830
|
+
nodeRoot: "nodeRoot_intrinsic",
|
|
1831
|
+
selectable: "selectable_intrinsic",
|
|
1832
|
+
rect: "rect_intrinsic",
|
|
1833
|
+
image: "image_intrinsic",
|
|
1834
|
+
imageMarker: "image_marker_intrinsic"
|
|
1835
|
+
};
|
|
1824
1836
|
const RECT = {
|
|
1825
1837
|
CORNER_RADIUS: 6,
|
|
1826
1838
|
MIN_SIZE: 10
|
|
@@ -1884,7 +1896,7 @@ var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "acce
|
|
|
1884
1896
|
width,
|
|
1885
1897
|
height,
|
|
1886
1898
|
cornerRadius: RECT.CORNER_RADIUS,
|
|
1887
|
-
name:
|
|
1899
|
+
name: `${NODE_NAMES.nodeRoot} ${NODE_NAMES.selectable} ${NODE_NAMES.rect}`,
|
|
1888
1900
|
draggable: true,
|
|
1889
1901
|
stroke: "black",
|
|
1890
1902
|
strokeWidth: 2
|
|
@@ -2003,7 +2015,7 @@ var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "acce
|
|
|
2003
2015
|
id: this.node.id,
|
|
2004
2016
|
x: this.node.props.x,
|
|
2005
2017
|
y: this.node.props.y,
|
|
2006
|
-
name:
|
|
2018
|
+
name: `${NODE_NAMES.nodeRoot} ${NODE_NAMES.selectable} ${NODE_NAMES.image}`,
|
|
2007
2019
|
draggable: true,
|
|
2008
2020
|
image: placeholder
|
|
2009
2021
|
});
|
|
@@ -2200,12 +2212,23 @@ var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "acce
|
|
|
2200
2212
|
__privateAdd(this, _markerGroup);
|
|
2201
2213
|
__privateAdd(this, _circle);
|
|
2202
2214
|
__privateAdd(this, _text);
|
|
2215
|
+
__privateAdd(this, _handleViewportChange);
|
|
2216
|
+
__privateAdd(this, _handleNodesSelected);
|
|
2203
2217
|
const group = this.getElement();
|
|
2204
2218
|
__privateSet(this, _rect, group.findOne(".rect"));
|
|
2205
2219
|
__privateSet(this, _markerGroup, group.findOne(".marker-group"));
|
|
2206
2220
|
__privateSet(this, _circle, __privateGet(this, _markerGroup).findOne("Circle"));
|
|
2207
2221
|
__privateSet(this, _text, __privateGet(this, _markerGroup).findOne("Text"));
|
|
2208
2222
|
__privateMethod(this, _ImageMarkerNode_instances, setupEventHandlers_fn3).call(this);
|
|
2223
|
+
__privateSet(this, _handleViewportChange, () => {
|
|
2224
|
+
__privateMethod(this, _ImageMarkerNode_instances, updateMarkerScale_fn).call(this);
|
|
2225
|
+
});
|
|
2226
|
+
this.core.on("viewport:scale:change", __privateGet(this, _handleViewportChange));
|
|
2227
|
+
__privateSet(this, _handleNodesSelected, (selectedIds) => {
|
|
2228
|
+
const isSelected = selectedIds.includes(this.node.id);
|
|
2229
|
+
this.setFocusState(isSelected);
|
|
2230
|
+
});
|
|
2231
|
+
this.core.on("nodes:selected", __privateGet(this, _handleNodesSelected));
|
|
2209
2232
|
}
|
|
2210
2233
|
createElement() {
|
|
2211
2234
|
const width = Math.max(
|
|
@@ -2218,23 +2241,27 @@ var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "acce
|
|
|
2218
2241
|
);
|
|
2219
2242
|
const group = new Konva.Group({
|
|
2220
2243
|
id: this.node.id,
|
|
2221
|
-
name:
|
|
2244
|
+
name: `${NODE_NAMES.nodeRoot} ${NODE_NAMES.imageMarker} ${this.node.meta.parent} ${NODE_NAMES.selectable}`,
|
|
2222
2245
|
x: this.node.props.x,
|
|
2223
2246
|
y: this.node.props.y,
|
|
2224
2247
|
width,
|
|
2225
2248
|
height
|
|
2226
2249
|
});
|
|
2250
|
+
const stageScale = this.core.getStageScale();
|
|
2251
|
+
const rectStrokeWidth = 2 / stageScale;
|
|
2252
|
+
const rectDash = [5 / stageScale, 5 / stageScale];
|
|
2253
|
+
const rectCornerRadius = RECT.CORNER_RADIUS / stageScale;
|
|
2227
2254
|
const rect = new Konva.Rect({
|
|
2228
2255
|
name: "rect",
|
|
2229
2256
|
x: 0,
|
|
2230
2257
|
y: 0,
|
|
2231
2258
|
width,
|
|
2232
2259
|
height,
|
|
2233
|
-
stroke:
|
|
2234
|
-
strokeWidth:
|
|
2235
|
-
dash:
|
|
2260
|
+
stroke: "#3B82F6",
|
|
2261
|
+
strokeWidth: rectStrokeWidth,
|
|
2262
|
+
dash: rectDash,
|
|
2236
2263
|
fill: "transparent",
|
|
2237
|
-
cornerRadius:
|
|
2264
|
+
cornerRadius: rectCornerRadius,
|
|
2238
2265
|
listening: false
|
|
2239
2266
|
});
|
|
2240
2267
|
const markerGroup = new Konva.Group({
|
|
@@ -2243,13 +2270,14 @@ var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "acce
|
|
|
2243
2270
|
y: height,
|
|
2244
2271
|
visible: this.isDraft ? false : true
|
|
2245
2272
|
});
|
|
2246
|
-
const
|
|
2247
|
-
const
|
|
2273
|
+
const radius = 14 / stageScale;
|
|
2274
|
+
const strokeWidth = 3 / stageScale;
|
|
2275
|
+
const fontSize = 16 / stageScale;
|
|
2248
2276
|
const circle = new Konva.Circle({
|
|
2249
2277
|
radius,
|
|
2250
|
-
fill: "
|
|
2251
|
-
stroke: "
|
|
2252
|
-
strokeWidth
|
|
2278
|
+
fill: "#3B82F6",
|
|
2279
|
+
stroke: "white",
|
|
2280
|
+
strokeWidth
|
|
2253
2281
|
});
|
|
2254
2282
|
const text = new Konva.Text({
|
|
2255
2283
|
x: -radius,
|
|
@@ -2259,7 +2287,7 @@ var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "acce
|
|
|
2259
2287
|
text: String(this.node.meta.markerNumber || ""),
|
|
2260
2288
|
align: "center",
|
|
2261
2289
|
verticalAlign: "middle",
|
|
2262
|
-
fontSize
|
|
2290
|
+
fontSize,
|
|
2263
2291
|
fill: "white"
|
|
2264
2292
|
});
|
|
2265
2293
|
markerGroup.add(circle);
|
|
@@ -2322,13 +2350,15 @@ var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "acce
|
|
|
2322
2350
|
* 销毁
|
|
2323
2351
|
*/
|
|
2324
2352
|
destroy() {
|
|
2353
|
+
this.core.off("viewport:scale:change", __privateGet(this, _handleViewportChange));
|
|
2354
|
+
this.core.off("nodes:selected", __privateGet(this, _handleNodesSelected));
|
|
2325
2355
|
this.element.destroy();
|
|
2326
2356
|
}
|
|
2327
2357
|
/**
|
|
2328
2358
|
* 更新焦点状态(hover 或 selected)
|
|
2329
2359
|
*/
|
|
2330
2360
|
setFocusState(isFocus) {
|
|
2331
|
-
const strokeWidth = isFocus ? 4 :
|
|
2361
|
+
const strokeWidth = isFocus ? 4 : 3;
|
|
2332
2362
|
const scale = isFocus ? 1.2 : 1;
|
|
2333
2363
|
__privateGet(this, _rect).strokeWidth(strokeWidth);
|
|
2334
2364
|
__privateGet(this, _circle).strokeWidth(strokeWidth);
|
|
@@ -2340,7 +2370,31 @@ var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "acce
|
|
|
2340
2370
|
_markerGroup = new WeakMap();
|
|
2341
2371
|
_circle = new WeakMap();
|
|
2342
2372
|
_text = new WeakMap();
|
|
2373
|
+
_handleViewportChange = new WeakMap();
|
|
2374
|
+
_handleNodesSelected = new WeakMap();
|
|
2343
2375
|
_ImageMarkerNode_instances = new WeakSet();
|
|
2376
|
+
/**
|
|
2377
|
+
* 更新标记点的缩放以保持视觉大小不变
|
|
2378
|
+
*/
|
|
2379
|
+
updateMarkerScale_fn = function() {
|
|
2380
|
+
const stageScale = this.core.getStageScale();
|
|
2381
|
+
const radius = 14 / stageScale;
|
|
2382
|
+
const strokeWidth = 3 / stageScale;
|
|
2383
|
+
const fontSize = 16 / stageScale;
|
|
2384
|
+
const rectStrokeWidth = 3 / stageScale;
|
|
2385
|
+
const rectDash = [5 / stageScale, 5 / stageScale];
|
|
2386
|
+
const rectCornerRadius = RECT.CORNER_RADIUS / stageScale;
|
|
2387
|
+
__privateGet(this, _rect).strokeWidth(rectStrokeWidth);
|
|
2388
|
+
__privateGet(this, _rect).dash(rectDash);
|
|
2389
|
+
__privateGet(this, _rect).cornerRadius(rectCornerRadius);
|
|
2390
|
+
__privateGet(this, _circle).radius(radius);
|
|
2391
|
+
__privateGet(this, _circle).strokeWidth(strokeWidth);
|
|
2392
|
+
__privateGet(this, _text).x(-radius);
|
|
2393
|
+
__privateGet(this, _text).y(-radius);
|
|
2394
|
+
__privateGet(this, _text).width(radius * 2);
|
|
2395
|
+
__privateGet(this, _text).height(radius * 2);
|
|
2396
|
+
__privateGet(this, _text).fontSize(fontSize);
|
|
2397
|
+
};
|
|
2344
2398
|
/**
|
|
2345
2399
|
* 设置事件处理器
|
|
2346
2400
|
*/
|
|
@@ -2402,8 +2456,7 @@ var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "acce
|
|
|
2402
2456
|
...baseNode,
|
|
2403
2457
|
style: {
|
|
2404
2458
|
...baseNode.style,
|
|
2405
|
-
color: "#
|
|
2406
|
-
line: "dashed"
|
|
2459
|
+
color: "#3B82F6"
|
|
2407
2460
|
}
|
|
2408
2461
|
};
|
|
2409
2462
|
}
|
|
@@ -2472,10 +2525,19 @@ var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "acce
|
|
|
2472
2525
|
toolType: "select",
|
|
2473
2526
|
nodes: []
|
|
2474
2527
|
});
|
|
2528
|
+
__privateAdd(this, _CanvasCore_instances);
|
|
2475
2529
|
__privateAdd(this, _canvasStage);
|
|
2476
2530
|
__privateAdd(this, _mainLayer);
|
|
2477
2531
|
__privateAdd(this, _canvasTransformer);
|
|
2478
2532
|
__privateAdd(this, _draftNode, null);
|
|
2533
|
+
__privateAdd(this, _container);
|
|
2534
|
+
__privateAdd(this, _handleKeyDown, (e) => {
|
|
2535
|
+
if (e.key === "Delete" || e.key === "Backspace") {
|
|
2536
|
+
e.preventDefault();
|
|
2537
|
+
this.deleteSelectedNodes();
|
|
2538
|
+
}
|
|
2539
|
+
});
|
|
2540
|
+
__privateSet(this, _container, el);
|
|
2479
2541
|
__privateSet(this, _canvasStage, new CanvasStage(this, {
|
|
2480
2542
|
container: el,
|
|
2481
2543
|
width: el.clientWidth,
|
|
@@ -2488,6 +2550,7 @@ var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "acce
|
|
|
2488
2550
|
__privateGet(this, _canvasStage).getStage().add(__privateGet(this, _mainLayer));
|
|
2489
2551
|
__privateGet(this, _mainLayer).add(__privateGet(this, _canvasTransformer).getTransformer());
|
|
2490
2552
|
this.updateViewport(this.getState().viewport, false);
|
|
2553
|
+
__privateMethod(this, _CanvasCore_instances, setupKeyboardEvents_fn).call(this);
|
|
2491
2554
|
}
|
|
2492
2555
|
/**
|
|
2493
2556
|
* 获取 CanvasStage 实例
|
|
@@ -2583,8 +2646,9 @@ var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "acce
|
|
|
2583
2646
|
*/
|
|
2584
2647
|
updateViewport(viewport, addToHistory = false) {
|
|
2585
2648
|
__privateGet(this, _canvasStage).setViewport(viewport);
|
|
2649
|
+
const oldViewport = this.getState().viewport;
|
|
2586
2650
|
const newViewport = {
|
|
2587
|
-
...
|
|
2651
|
+
...oldViewport,
|
|
2588
2652
|
...viewport
|
|
2589
2653
|
};
|
|
2590
2654
|
this._updateState(
|
|
@@ -2594,6 +2658,9 @@ var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "acce
|
|
|
2594
2658
|
addToHistory
|
|
2595
2659
|
);
|
|
2596
2660
|
this.emit("viewport:change", newViewport);
|
|
2661
|
+
if (oldViewport.scale !== newViewport.scale) {
|
|
2662
|
+
this.emit("viewport:scale:change", newViewport.scale);
|
|
2663
|
+
}
|
|
2597
2664
|
__privateGet(this, _canvasTransformer).emitPositionChange();
|
|
2598
2665
|
}
|
|
2599
2666
|
createNodes(nodes) {
|
|
@@ -2641,7 +2708,7 @@ var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "acce
|
|
|
2641
2708
|
visible: true
|
|
2642
2709
|
},
|
|
2643
2710
|
style: {
|
|
2644
|
-
color: "#
|
|
2711
|
+
color: "#3B82F6",
|
|
2645
2712
|
line: "dashed",
|
|
2646
2713
|
size: "medium",
|
|
2647
2714
|
opacity: 1
|
|
@@ -2789,41 +2856,79 @@ var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "acce
|
|
|
2789
2856
|
*/
|
|
2790
2857
|
selectNode(nodeId, multiSelect = false) {
|
|
2791
2858
|
const curSelectedNodeIds = this.getState().selectedNodeIds ?? [];
|
|
2792
|
-
|
|
2859
|
+
let selectedNodeIds = [];
|
|
2860
|
+
if (nodeId) {
|
|
2861
|
+
if (multiSelect && curSelectedNodeIds.length > 0) {
|
|
2862
|
+
selectedNodeIds = [...curSelectedNodeIds, nodeId];
|
|
2863
|
+
} else {
|
|
2864
|
+
selectedNodeIds = [nodeId];
|
|
2865
|
+
}
|
|
2866
|
+
} else if (curSelectedNodeIds.length === 0) {
|
|
2793
2867
|
return;
|
|
2794
2868
|
}
|
|
2795
|
-
if (
|
|
2869
|
+
if (selectedNodeIds.length === 0) {
|
|
2796
2870
|
__privateGet(this, _canvasTransformer).clearNodes();
|
|
2797
|
-
this._updateState(
|
|
2798
|
-
{
|
|
2799
|
-
selectedNodeIds: []
|
|
2800
|
-
},
|
|
2801
|
-
false
|
|
2802
|
-
);
|
|
2803
|
-
return;
|
|
2804
|
-
}
|
|
2805
|
-
let selectedNodeIds = [];
|
|
2806
|
-
if (multiSelect) {
|
|
2807
|
-
selectedNodeIds = curSelectedNodeIds.length ? [...curSelectedNodeIds, nodeId] : [nodeId];
|
|
2808
2871
|
} else {
|
|
2809
|
-
|
|
2872
|
+
const nodes = this.getStage().find(`.${NODE_NAMES.selectable}`).filter((node) => selectedNodeIds.includes(node.id()));
|
|
2873
|
+
__privateGet(this, _canvasTransformer).setNodes(nodes);
|
|
2810
2874
|
}
|
|
2811
|
-
|
|
2812
|
-
|
|
2813
|
-
|
|
2875
|
+
this._updateState({ selectedNodeIds }, false);
|
|
2876
|
+
this.emit("nodes:selected", selectedNodeIds);
|
|
2877
|
+
}
|
|
2878
|
+
/**
|
|
2879
|
+
* 删除指定的节点(内部使用)
|
|
2880
|
+
* 如果删除的是 image 节点,会同步删除所有关联的 image-marker
|
|
2881
|
+
* @internal 仅供内部使用,外部请使用 CanvasApi
|
|
2882
|
+
* @param nodeIds - 要删除的节点 ID 数组
|
|
2883
|
+
* @returns 被删除的节点数据数组
|
|
2884
|
+
*/
|
|
2885
|
+
deleteNodes(nodeIds) {
|
|
2886
|
+
if (nodeIds.length === 0) return [];
|
|
2887
|
+
const nodes = this.getState().nodes || [];
|
|
2888
|
+
const idsToDelete = new Set(nodeIds);
|
|
2889
|
+
nodeIds.forEach((id) => {
|
|
2890
|
+
const node = nodes.find((n) => n.id === id);
|
|
2891
|
+
if (node?.type === "image") {
|
|
2892
|
+
nodes.forEach((n) => {
|
|
2893
|
+
if (n.type === "image-marker" && n.meta.parent === id) {
|
|
2894
|
+
idsToDelete.add(n.id);
|
|
2895
|
+
}
|
|
2896
|
+
});
|
|
2897
|
+
}
|
|
2814
2898
|
});
|
|
2815
|
-
|
|
2899
|
+
const deletedNodes = nodes.filter((n) => idsToDelete.has(n.id));
|
|
2900
|
+
idsToDelete.forEach((id) => {
|
|
2901
|
+
const shape = this.getStage().findOne(`#${id}`);
|
|
2902
|
+
if (shape) {
|
|
2903
|
+
shape.destroy();
|
|
2904
|
+
}
|
|
2905
|
+
});
|
|
2906
|
+
const newNodes = nodes.filter((n) => !idsToDelete.has(n.id));
|
|
2907
|
+
__privateGet(this, _canvasTransformer).clearNodes();
|
|
2816
2908
|
this._updateState(
|
|
2817
2909
|
{
|
|
2818
|
-
|
|
2910
|
+
nodes: newNodes,
|
|
2911
|
+
selectedNodeIds: []
|
|
2819
2912
|
},
|
|
2820
|
-
|
|
2913
|
+
true
|
|
2821
2914
|
);
|
|
2915
|
+
this.emit("nodes:deleted", deletedNodes);
|
|
2916
|
+
return deletedNodes;
|
|
2917
|
+
}
|
|
2918
|
+
/**
|
|
2919
|
+
* 删除选中的节点(内部使用)
|
|
2920
|
+
* @internal 仅供内部使用,外部请使用 CanvasApi
|
|
2921
|
+
*/
|
|
2922
|
+
deleteSelectedNodes() {
|
|
2923
|
+
const selectedNodeIds = this.getState().selectedNodeIds || [];
|
|
2924
|
+
if (selectedNodeIds.length === 0) return;
|
|
2925
|
+
this.deleteNodes(selectedNodeIds);
|
|
2822
2926
|
}
|
|
2823
2927
|
/**
|
|
2824
2928
|
* 销毁 canvas
|
|
2825
2929
|
*/
|
|
2826
2930
|
dispose() {
|
|
2931
|
+
__privateGet(this, _container).removeEventListener("keydown", __privateGet(this, _handleKeyDown));
|
|
2827
2932
|
this.getCanvasTransformer().destroy();
|
|
2828
2933
|
this.getMainLayer().destroy();
|
|
2829
2934
|
this.getCanvasStage().destroy();
|
|
@@ -2879,6 +2984,16 @@ var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "acce
|
|
|
2879
2984
|
_mainLayer = new WeakMap();
|
|
2880
2985
|
_canvasTransformer = new WeakMap();
|
|
2881
2986
|
_draftNode = new WeakMap();
|
|
2987
|
+
_container = new WeakMap();
|
|
2988
|
+
_handleKeyDown = new WeakMap();
|
|
2989
|
+
_CanvasCore_instances = new WeakSet();
|
|
2990
|
+
/**
|
|
2991
|
+
* 设置键盘事件监听
|
|
2992
|
+
*/
|
|
2993
|
+
setupKeyboardEvents_fn = function() {
|
|
2994
|
+
__privateGet(this, _container).tabIndex = 0;
|
|
2995
|
+
__privateGet(this, _container).addEventListener("keydown", __privateGet(this, _handleKeyDown));
|
|
2996
|
+
};
|
|
2882
2997
|
class CanvasApi extends CanvasCore {
|
|
2883
2998
|
/**
|
|
2884
2999
|
* 获取所有可用的工具类型
|
|
@@ -2899,6 +3014,14 @@ var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "acce
|
|
|
2899
3014
|
createNodes(nodes) {
|
|
2900
3015
|
super.createNodes(nodes);
|
|
2901
3016
|
}
|
|
3017
|
+
/**
|
|
3018
|
+
* 根据 ID 获取节点
|
|
3019
|
+
*/
|
|
3020
|
+
getNodeById(id) {
|
|
3021
|
+
const nodes = this.getState().nodes || [];
|
|
3022
|
+
const node = nodes.find((n) => n.id === id);
|
|
3023
|
+
return node || null;
|
|
3024
|
+
}
|
|
2902
3025
|
/**
|
|
2903
3026
|
* 更新视口位置
|
|
2904
3027
|
*/
|
|
@@ -2959,38 +3082,75 @@ var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "acce
|
|
|
2959
3082
|
* @returns DataURL 格式的图片数据,如果没有选区则返回 null
|
|
2960
3083
|
*/
|
|
2961
3084
|
exportSelectionAsImage(options) {
|
|
2962
|
-
const
|
|
2963
|
-
if (
|
|
3085
|
+
const selectedNodeIds = this.getState().selectedNodeIds || [];
|
|
3086
|
+
if (selectedNodeIds.length === 0) {
|
|
2964
3087
|
console.warn("No selection to export");
|
|
2965
3088
|
return null;
|
|
2966
3089
|
}
|
|
2967
|
-
const stage = this.getStage();
|
|
2968
3090
|
const padding = options?.padding ?? 0;
|
|
2969
|
-
const
|
|
2970
|
-
|
|
2971
|
-
|
|
2972
|
-
|
|
2973
|
-
|
|
2974
|
-
|
|
2975
|
-
|
|
2976
|
-
|
|
2977
|
-
|
|
2978
|
-
|
|
2979
|
-
|
|
2980
|
-
|
|
2981
|
-
|
|
2982
|
-
|
|
2983
|
-
|
|
3091
|
+
const tempGroup = new Konva.Group();
|
|
3092
|
+
selectedNodeIds.forEach((id) => {
|
|
3093
|
+
const shape = this.getStage().findOne(`#${id}`);
|
|
3094
|
+
if (shape) {
|
|
3095
|
+
const clone = shape.clone();
|
|
3096
|
+
tempGroup.add(clone);
|
|
3097
|
+
}
|
|
3098
|
+
});
|
|
3099
|
+
const box = tempGroup.getClientRect();
|
|
3100
|
+
const dataURL = tempGroup.toDataURL({
|
|
3101
|
+
x: box.x - padding,
|
|
3102
|
+
y: box.y - padding,
|
|
3103
|
+
width: box.width + padding * 2,
|
|
3104
|
+
height: box.height + padding * 2,
|
|
3105
|
+
pixelRatio: options?.pixelRatio ?? 2,
|
|
3106
|
+
mimeType: options?.mimeType ?? "image/png",
|
|
3107
|
+
quality: options?.quality ?? 1
|
|
3108
|
+
});
|
|
3109
|
+
tempGroup.destroy();
|
|
3110
|
+
return dataURL;
|
|
3111
|
+
}
|
|
3112
|
+
/**
|
|
3113
|
+
* 导出带有标注的图片节点为图片
|
|
3114
|
+
* @param id - 图片节点 ID
|
|
3115
|
+
* @returns DataURL 格式的图片数据,如果节点不存在则返回 null
|
|
3116
|
+
*/
|
|
3117
|
+
exportImageWithMarker(id) {
|
|
3118
|
+
const imageShape = this.getStage().findOne(`#${id}`);
|
|
3119
|
+
if (!imageShape) {
|
|
3120
|
+
console.warn("Image shape not found on stage");
|
|
3121
|
+
return null;
|
|
2984
3122
|
}
|
|
3123
|
+
const nodes = this.getState().nodes || [];
|
|
3124
|
+
const markerNodes = nodes.filter(
|
|
3125
|
+
(n) => n.type === "image-marker" && n.meta.parent === id
|
|
3126
|
+
);
|
|
3127
|
+
const tempGroup = new Konva.Group();
|
|
3128
|
+
const imageClone = imageShape.clone();
|
|
3129
|
+
tempGroup.add(imageClone);
|
|
3130
|
+
markerNodes.forEach((markerNode) => {
|
|
3131
|
+
const markerShape = this.getStage().findOne(`#${markerNode.id}`);
|
|
3132
|
+
if (markerShape) {
|
|
3133
|
+
const markerClone = markerShape.clone();
|
|
3134
|
+
tempGroup.add(markerClone);
|
|
3135
|
+
}
|
|
3136
|
+
});
|
|
3137
|
+
const box = tempGroup.getClientRect();
|
|
3138
|
+
const dataURL = tempGroup.toDataURL({
|
|
3139
|
+
x: box.x,
|
|
3140
|
+
y: box.y,
|
|
3141
|
+
width: box.width,
|
|
3142
|
+
height: box.height,
|
|
3143
|
+
pixelRatio: 2
|
|
3144
|
+
});
|
|
3145
|
+
tempGroup.destroy();
|
|
3146
|
+
return dataURL;
|
|
2985
3147
|
}
|
|
2986
3148
|
/**
|
|
2987
3149
|
* 删除当前选中的节点
|
|
2988
3150
|
* 如果删除的是 image 节点,会同步删除所有关联的 image-marker
|
|
2989
3151
|
*/
|
|
2990
3152
|
deleteSelectedNodes() {
|
|
2991
|
-
|
|
2992
|
-
if (selectedNodeIds.length === 0) return;
|
|
2993
|
-
this.deleteNodes(selectedNodeIds);
|
|
3153
|
+
super.deleteSelectedNodes();
|
|
2994
3154
|
}
|
|
2995
3155
|
/**
|
|
2996
3156
|
* 删除指定的节点
|
|
@@ -2999,37 +3159,7 @@ var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "acce
|
|
|
2999
3159
|
* @returns 被删除的节点数据数组
|
|
3000
3160
|
*/
|
|
3001
3161
|
deleteNodes(nodeIds) {
|
|
3002
|
-
|
|
3003
|
-
const nodes = this.getState().nodes || [];
|
|
3004
|
-
const idsToDelete = new Set(nodeIds);
|
|
3005
|
-
nodeIds.forEach((id) => {
|
|
3006
|
-
const node = nodes.find((n) => n.id === id);
|
|
3007
|
-
if (node?.type === "image") {
|
|
3008
|
-
nodes.forEach((n) => {
|
|
3009
|
-
if (n.type === "image-marker" && n.meta.parent === id) {
|
|
3010
|
-
idsToDelete.add(n.id);
|
|
3011
|
-
}
|
|
3012
|
-
});
|
|
3013
|
-
}
|
|
3014
|
-
});
|
|
3015
|
-
const deletedNodes = nodes.filter((n) => idsToDelete.has(n.id));
|
|
3016
|
-
idsToDelete.forEach((id) => {
|
|
3017
|
-
const shape = this.getStage().findOne(`#${id}`);
|
|
3018
|
-
if (shape) {
|
|
3019
|
-
shape.destroy();
|
|
3020
|
-
}
|
|
3021
|
-
});
|
|
3022
|
-
const newNodes = nodes.filter((n) => !idsToDelete.has(n.id));
|
|
3023
|
-
this.getCanvasTransformer().clearNodes();
|
|
3024
|
-
this._updateState(
|
|
3025
|
-
{
|
|
3026
|
-
nodes: newNodes,
|
|
3027
|
-
selectedNodeIds: []
|
|
3028
|
-
},
|
|
3029
|
-
true
|
|
3030
|
-
);
|
|
3031
|
-
this.emit("nodes:deleted", deletedNodes);
|
|
3032
|
-
return deletedNodes;
|
|
3162
|
+
return super.deleteNodes(nodeIds);
|
|
3033
3163
|
}
|
|
3034
3164
|
/**
|
|
3035
3165
|
* 滚动到内容区域
|
|
@@ -3057,7 +3187,7 @@ var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "acce
|
|
|
3057
3187
|
const hasSelection = !hasTargetIds && selectedNodeIds.length > 0;
|
|
3058
3188
|
const idsToShow = hasTargetIds ? targetNodeIds : hasSelection ? selectedNodeIds : null;
|
|
3059
3189
|
mainLayer.children.forEach((child) => {
|
|
3060
|
-
if (child.visible() && child.getClassName() !== "Transformer" && child.hasName(
|
|
3190
|
+
if (child.visible() && child.getClassName() !== "Transformer" && child.hasName(NODE_NAMES.selectable)) {
|
|
3061
3191
|
if (idsToShow) {
|
|
3062
3192
|
const id = child.id();
|
|
3063
3193
|
if (!idsToShow.includes(id)) return;
|
|
@@ -3374,7 +3504,7 @@ var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "acce
|
|
|
3374
3504
|
] });
|
|
3375
3505
|
}
|
|
3376
3506
|
exports2.CanvasApi = CanvasApi;
|
|
3377
|
-
exports2.
|
|
3507
|
+
exports2.NODE_NAMES = NODE_NAMES;
|
|
3378
3508
|
exports2.PureCanvas = PureCanvas;
|
|
3379
3509
|
Object.defineProperty(exports2, Symbol.toStringTag, { value: "Module" });
|
|
3380
3510
|
}));
|