@logicflow/core 2.0.16 → 2.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/.turbo/turbo-build$colon$dev.log +2 -2
  2. package/.turbo/turbo-build.log +5 -5
  3. package/CHANGELOG.md +22 -0
  4. package/dist/index.min.js +1 -1
  5. package/dist/index.min.js.map +1 -1
  6. package/es/LogicFlow.js +4 -1
  7. package/es/constant/index.d.ts +3 -1
  8. package/es/constant/index.js +2 -0
  9. package/es/keyboard/shortcut.js +7 -0
  10. package/es/model/GraphModel.js +2 -0
  11. package/es/model/SnaplineModel.d.ts +2 -1
  12. package/es/model/SnaplineModel.js +26 -11
  13. package/es/options.d.ts +1 -0
  14. package/es/util/resize.d.ts +12 -10
  15. package/es/util/resize.js +160 -81
  16. package/es/view/Control.d.ts +5 -1
  17. package/es/view/Control.js +23 -2
  18. package/es/view/behavior/dnd.js +3 -0
  19. package/lib/LogicFlow.js +4 -1
  20. package/lib/constant/index.d.ts +3 -1
  21. package/lib/constant/index.js +2 -0
  22. package/lib/keyboard/shortcut.js +7 -0
  23. package/lib/model/GraphModel.js +2 -0
  24. package/lib/model/SnaplineModel.d.ts +2 -1
  25. package/lib/model/SnaplineModel.js +26 -11
  26. package/lib/options.d.ts +1 -0
  27. package/lib/util/resize.d.ts +12 -10
  28. package/lib/util/resize.js +162 -83
  29. package/lib/view/Control.d.ts +5 -1
  30. package/lib/view/Control.js +22 -1
  31. package/lib/view/behavior/dnd.js +3 -0
  32. package/package.json +1 -1
  33. package/src/LogicFlow.tsx +7 -2
  34. package/src/constant/index.ts +2 -0
  35. package/src/keyboard/shortcut.ts +6 -0
  36. package/src/model/GraphModel.ts +2 -0
  37. package/src/model/SnaplineModel.ts +29 -11
  38. package/src/options.ts +1 -0
  39. package/src/util/resize.ts +200 -112
  40. package/src/view/Control.tsx +29 -5
  41. package/src/view/behavior/dnd.ts +3 -0
  42. package/stats.html +1 -1
@@ -95,6 +95,7 @@ var EventType;
95
95
  EventType["BLANK_DRAG"] = "blank:drag";
96
96
  EventType["BLANK_DROP"] = "blank:drop";
97
97
  EventType["BLANK_MOUSEMOVE"] = "blank:mousemove";
98
+ EventType["BLANK_CANVAS_MOUSEMOVE"] = "blank:canvas-mousemove";
98
99
  EventType["BLANK_MOUSEUP"] = "blank:mouseup";
99
100
  EventType["BLANK_CLICK"] = "blank:click";
100
101
  EventType["BLANK_CONTEXTMENU"] = "blank:contextmenu";
@@ -147,6 +148,7 @@ var EventType;
147
148
  EventType["GRAPH_TRANSFORM"] = "graph:transform";
148
149
  EventType["GRAPH_RENDERED"] = "graph:rendered";
149
150
  EventType["GRAPH_UPDATED"] = "graph:updated";
151
+ EventType["EDIT_CONFIG_CHANGED"] = "editConfig:changed";
150
152
  })(EventType || (exports.EventType = EventType = {}));
151
153
  var OverlapMode;
152
154
  (function (OverlapMode) {
@@ -27,12 +27,19 @@ var lodash_es_1 = require("lodash-es");
27
27
  var lodash_es_2 = require("lodash-es");
28
28
  var selected = null;
29
29
  function translateNodeData(nodeData, distance) {
30
+ var _a, _b;
30
31
  nodeData.x += distance;
31
32
  nodeData.y += distance;
32
33
  if (!(0, lodash_es_1.isEmpty)(nodeData.text)) {
33
34
  nodeData.text.x += distance;
34
35
  nodeData.text.y += distance;
35
36
  }
37
+ if (!(0, lodash_es_1.isEmpty)((_a = nodeData.properties) === null || _a === void 0 ? void 0 : _a._label)) {
38
+ (_b = nodeData.properties) === null || _b === void 0 ? void 0 : _b._label.forEach(function (label) {
39
+ label.x += distance;
40
+ label.y += distance;
41
+ });
42
+ }
36
43
  return nodeData;
37
44
  }
38
45
  exports.translateNodeData = translateNodeData;
@@ -875,6 +875,8 @@ var GraphModel = /** @class */ (function () {
875
875
  }
876
876
  if (edgeOriginData.id && this.edgesMap[edgeOriginData.id]) {
877
877
  delete edgeOriginData.id;
878
+ delete edgeOriginData.sourceAnchorId;
879
+ delete edgeOriginData.targetAnchorId;
878
880
  }
879
881
  var Model = this.getModel(type);
880
882
  if (!Model) {
@@ -12,7 +12,8 @@ export declare class SnaplineModel {
12
12
  isShowHorizontal: boolean;
13
13
  isShowVertical: boolean;
14
14
  position: Position;
15
- constructor(graphModel: GraphModel);
15
+ epsilon: number;
16
+ constructor(graphModel: GraphModel, epsilon?: number);
16
17
  getStyle(): {
17
18
  [x: string]: unknown;
18
19
  fill?: string | undefined;
@@ -21,7 +21,8 @@ exports.SnaplineModel = void 0;
21
21
  var mobx_1 = require("mobx");
22
22
  var util_1 = require("../util");
23
23
  var SnaplineModel = /** @class */ (function () {
24
- function SnaplineModel(graphModel) {
24
+ function SnaplineModel(graphModel, epsilon) {
25
+ if (epsilon === void 0) { epsilon = 1; }
25
26
  this.isShowHorizontal = false;
26
27
  this.isShowVertical = false;
27
28
  this.position = {
@@ -29,6 +30,7 @@ var SnaplineModel = /** @class */ (function () {
29
30
  y: 0,
30
31
  };
31
32
  this.graphModel = graphModel;
33
+ this.epsilon = epsilon;
32
34
  }
33
35
  SnaplineModel.prototype.getStyle = function () {
34
36
  return __assign({}, this.graphModel.theme.snapline);
@@ -42,10 +44,10 @@ var SnaplineModel = /** @class */ (function () {
42
44
  var item = nodes[i];
43
45
  // 排除当前节点
44
46
  if (item.id !== draggingNode.id) {
45
- if (x === item.x) {
47
+ if (equal(x, item.x, this.epsilon)) {
46
48
  isShowVertical = true;
47
49
  }
48
- if (y === item.y) {
50
+ if (equal(y, item.y, this.epsilon)) {
49
51
  isShowHorizontal = true;
50
52
  }
51
53
  // 如果水平垂直都显示,则停止循环。减少不必要的遍历
@@ -87,15 +89,15 @@ var SnaplineModel = /** @class */ (function () {
87
89
  if (item.id !== draggingNode.id) {
88
90
  var itemData = (0, util_1.getNodeBBox)(item);
89
91
  // 如果节点的最大最小Y轴坐标与节点的最大最小Y轴坐标相等,展示水平线
90
- if (itemData.minY === (draggingData === null || draggingData === void 0 ? void 0 : draggingData.minY) ||
91
- itemData.maxY === (draggingData === null || draggingData === void 0 ? void 0 : draggingData.minY)) {
92
+ if (equal(itemData.minY, draggingData === null || draggingData === void 0 ? void 0 : draggingData.minY, this.epsilon) ||
93
+ equal(itemData.maxY, draggingData === null || draggingData === void 0 ? void 0 : draggingData.minY, this.epsilon)) {
92
94
  // 找到则停止循环。减少不必要的遍历
93
95
  isShowHorizontal = true;
94
96
  horizontalY = draggingData.minY;
95
97
  break;
96
98
  }
97
- if (itemData.minY === (draggingData === null || draggingData === void 0 ? void 0 : draggingData.maxY) ||
98
- itemData.maxY === (draggingData === null || draggingData === void 0 ? void 0 : draggingData.maxY)) {
99
+ if (equal(itemData.minY, draggingData === null || draggingData === void 0 ? void 0 : draggingData.maxY, this.epsilon) ||
100
+ equal(itemData.maxY, draggingData === null || draggingData === void 0 ? void 0 : draggingData.maxY, this.epsilon)) {
99
101
  isShowHorizontal = true;
100
102
  horizontalY = draggingData.maxY;
101
103
  break;
@@ -132,15 +134,20 @@ var SnaplineModel = /** @class */ (function () {
132
134
  if (item.id !== draggingNode.id) {
133
135
  var itemData = (0, util_1.getNodeBBox)(item);
134
136
  // 如果节点的最大最小X轴坐标与节点的最大最小X轴坐标相等,展示垂直线
135
- if (itemData.minX === (draggingData === null || draggingData === void 0 ? void 0 : draggingData.minX) ||
136
- itemData.maxX === (draggingData === null || draggingData === void 0 ? void 0 : draggingData.minX)) {
137
+ if (equal(itemData.minX, draggingData === null || draggingData === void 0 ? void 0 : draggingData.minX, this.epsilon)) {
138
+ isShowVertical = true;
139
+ verticalX = draggingData.minX;
140
+ break;
141
+ }
142
+ if (equal(itemData.minX, draggingData === null || draggingData === void 0 ? void 0 : draggingData.minX, this.epsilon) ||
143
+ equal(itemData.maxX, draggingData === null || draggingData === void 0 ? void 0 : draggingData.minX, this.epsilon)) {
137
144
  // 找到则停止循环。减少不必要的遍历
138
145
  isShowVertical = true;
139
146
  verticalX = draggingData.minX;
140
147
  break;
141
148
  }
142
- if (itemData.minX === (draggingData === null || draggingData === void 0 ? void 0 : draggingData.maxX) ||
143
- itemData.maxX === (draggingData === null || draggingData === void 0 ? void 0 : draggingData.maxX)) {
149
+ if (equal(itemData.minX, draggingData === null || draggingData === void 0 ? void 0 : draggingData.maxX, this.epsilon) ||
150
+ equal(itemData.maxX, draggingData === null || draggingData === void 0 ? void 0 : draggingData.maxX, this.epsilon)) {
144
151
  isShowVertical = true;
145
152
  verticalX = draggingData.maxX;
146
153
  break;
@@ -216,4 +223,12 @@ var SnaplineModel = /** @class */ (function () {
216
223
  return SnaplineModel;
217
224
  }());
218
225
  exports.SnaplineModel = SnaplineModel;
226
+ function equal(num1, num2, epsilon) {
227
+ if (Math.abs(num1 - num2) <= epsilon) {
228
+ return true;
229
+ }
230
+ else {
231
+ return false;
232
+ }
233
+ }
219
234
  exports.default = SnaplineModel;
package/lib/options.d.ts CHANGED
@@ -56,6 +56,7 @@ export declare namespace Options {
56
56
  history?: boolean;
57
57
  outline?: boolean;
58
58
  snapline?: boolean;
59
+ snaplineEpsilon?: number;
59
60
  textEdit?: boolean;
60
61
  guards?: GuardsConfig;
61
62
  overlapMode?: OverlapMode;
@@ -3,6 +3,14 @@ import { BaseNodeModel, GraphModel } from '../model';
3
3
  import ResizeInfo = ResizeControl.ResizeInfo;
4
4
  import ResizeNodeData = ResizeControl.ResizeNodeData;
5
5
  import type { SimplePoint } from '../algorithm/rotate';
6
+ export declare function calculateWidthAndHeight(startRotatedTouchControlPoint: SimplePoint, endRotatedTouchControlPoint: SimplePoint, oldCenter: SimplePoint, angle: number, freezeWidth: boolean | undefined, freezeHeight: boolean | undefined, oldWidth: number, oldHeight: number): {
7
+ width: number;
8
+ height: number;
9
+ center: {
10
+ x: number;
11
+ y: number;
12
+ };
13
+ };
6
14
  /**
7
15
  * 计算 Control 拖动后,节点的高度信息
8
16
  * @param index
@@ -11,7 +19,7 @@ import type { SimplePoint } from '../algorithm/rotate';
11
19
  * @param freezeWidth
12
20
  * @param freezeHeight
13
21
  */
14
- export declare const recalcResizeInfo: (index: ResizeControlIndex, resizeInfo: ResizeInfo, pct: number | undefined, freezeWidth: boolean | undefined, freezeHeight: boolean | undefined, rotate: number | undefined, controlX: number | undefined, controlY: number | undefined, oldCenterX: number, oldCenterY: number) => ResizeInfo;
22
+ export declare const recalcResizeInfo: (index: ResizeControlIndex, resizeInfo: ResizeInfo, pct: number | undefined, freezeWidth: boolean | undefined, freezeHeight: boolean | undefined, rotate: number | undefined, controlX: number | undefined, controlY: number | undefined, oldCenterX: number, oldCenterY: number, forceProportional?: boolean) => ResizeInfo;
15
23
  export declare const updateEdgePointByAnchors: (nodeModel: BaseNodeModel, graphModel: GraphModel) => void;
16
24
  export declare const triggerResizeEvent: (preNodeData: ResizeNodeData, curNodeData: ResizeNodeData, deltaX: number, deltaY: number, index: number, nodeModel: BaseNodeModel, graphModel: GraphModel) => void;
17
25
  export type IHandleResizeParams = {
@@ -23,6 +31,7 @@ export type IHandleResizeParams = {
23
31
  nodeModel: BaseNodeModel;
24
32
  graphModel: GraphModel;
25
33
  cancelCallback?: () => void;
34
+ forceProportional?: boolean;
26
35
  };
27
36
  /**
28
37
  * 处理节点的 resize 事件,提出来放到 utils 中,方便在外面(extension)中使用
@@ -34,13 +43,6 @@ export type IHandleResizeParams = {
34
43
  * @param nodeModel
35
44
  * @param graphModel
36
45
  * @param cancelCallback
46
+ * @param forceProportional
37
47
  */
38
- export declare const handleResize: ({ x, y, deltaX, deltaY, index, nodeModel, graphModel, cancelCallback, }: IHandleResizeParams) => void;
39
- export declare function calculateWidthAndHeight(startRotatedTouchControlPoint: SimplePoint, endRotatedTouchControlPoint: SimplePoint, oldCenter: SimplePoint, angle: number, freezeWidth: boolean | undefined, freezeHeight: boolean | undefined, oldWidth: number, oldHeight: number): {
40
- width: number;
41
- height: number;
42
- center: {
43
- x: number;
44
- y: number;
45
- };
46
- };
48
+ export declare const handleResize: ({ x, y, deltaX, deltaY, index, nodeModel, graphModel, cancelCallback, forceProportional, }: IHandleResizeParams) => void;
@@ -1,10 +1,88 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.calculateWidthAndHeight = exports.handleResize = exports.triggerResizeEvent = exports.updateEdgePointByAnchors = exports.recalcResizeInfo = void 0;
3
+ exports.handleResize = exports.triggerResizeEvent = exports.updateEdgePointByAnchors = exports.recalcResizeInfo = exports.calculateWidthAndHeight = void 0;
4
4
  var Control_1 = require("../view/Control");
5
5
  var lodash_es_1 = require("lodash-es");
6
6
  var constant_1 = require("../constant");
7
7
  var rotate_1 = require("../algorithm/rotate");
8
+ function calculateWidthAndHeight(startRotatedTouchControlPoint, endRotatedTouchControlPoint, oldCenter, angle, freezeWidth, freezeHeight, oldWidth, oldHeight) {
9
+ if (freezeWidth === void 0) { freezeWidth = false; }
10
+ if (freezeHeight === void 0) { freezeHeight = false; }
11
+ // 假设目前触摸的是右下角的control点
12
+ // 计算出来左上角的control坐标,resize过程左上角的control坐标保持不变
13
+ var freezePoint = {
14
+ x: oldCenter.x - (startRotatedTouchControlPoint.x - oldCenter.x),
15
+ y: oldCenter.y - (startRotatedTouchControlPoint.y - oldCenter.y),
16
+ };
17
+ // 【touchEndPoint】右下角 + freezePoint左上角 计算出新的中心点
18
+ var newCenter = (0, rotate_1.getNewCenter)(freezePoint, endRotatedTouchControlPoint);
19
+ // 得到【touchEndPoint】右下角-没有transform的坐标
20
+ var endZeroTouchControlPoint = (0, rotate_1.calculatePointAfterRotateAngle)(endRotatedTouchControlPoint, newCenter, -angle);
21
+ // ---------- 使用transform之前的坐标计算出新的width和height ----------
22
+ // 得到左上角---没有transform的坐标
23
+ var zeroFreezePoint = (0, rotate_1.calculatePointAfterRotateAngle)(freezePoint, newCenter, -angle);
24
+ if (freezeWidth) {
25
+ // 如果固定width,那么不能单纯使用endZeroTouchControlPoint.x=startZeroTouchControlPoint.x
26
+ // 因为去掉transform的左上角不一定是重合的,我们要保证的是transform后的左上角重合
27
+ var newWidth = Math.abs(endZeroTouchControlPoint.x - zeroFreezePoint.x);
28
+ var widthDx = newWidth - oldWidth;
29
+ // 点击的是左边锚点,是+widthDx/2,点击是右边锚点,是-widthDx/2
30
+ if (newCenter.x > endZeroTouchControlPoint.x) {
31
+ // 当前触摸的是左边锚点
32
+ newCenter.x = newCenter.x + widthDx / 2;
33
+ }
34
+ else {
35
+ // 当前触摸的是右边锚点
36
+ newCenter.x = newCenter.x - widthDx / 2;
37
+ }
38
+ }
39
+ if (freezeHeight) {
40
+ var newHeight = Math.abs(endZeroTouchControlPoint.y - zeroFreezePoint.y);
41
+ var heightDy = newHeight - oldHeight;
42
+ if (newCenter.y > endZeroTouchControlPoint.y) {
43
+ // 当前触摸的是上边锚点
44
+ newCenter.y = newCenter.y + heightDy / 2;
45
+ }
46
+ else {
47
+ newCenter.y = newCenter.y - heightDy / 2;
48
+ }
49
+ }
50
+ if (freezeWidth || freezeHeight) {
51
+ // 如果调整过transform之前的坐标,那么transform后的坐标也会改变,那么算出来的newCenter也得调整
52
+ // 由于无论如何rotate,中心点都是不变的,因此我们可以使用transform之前的坐标算出新的中心点
53
+ var nowFreezePoint = (0, rotate_1.calculatePointAfterRotateAngle)(zeroFreezePoint, newCenter, angle);
54
+ // 得到当前新rect的左上角与实际上transform后的左上角的偏移量
55
+ var dx = nowFreezePoint.x - freezePoint.x;
56
+ var dy = nowFreezePoint.y - freezePoint.y;
57
+ // 修正不使用transform的坐标: 左上角、右下角、center
58
+ newCenter.x = newCenter.x - dx;
59
+ newCenter.y = newCenter.y - dy;
60
+ zeroFreezePoint = (0, rotate_1.calculatePointAfterRotateAngle)(freezePoint, newCenter, -angle);
61
+ endZeroTouchControlPoint = {
62
+ x: newCenter.x - (zeroFreezePoint.x - newCenter.x),
63
+ y: newCenter.y - (zeroFreezePoint.y - newCenter.y),
64
+ };
65
+ }
66
+ // transform之前的坐标的左上角+右下角计算出宽度和高度
67
+ var width = Math.abs(endZeroTouchControlPoint.x - zeroFreezePoint.x);
68
+ var height = Math.abs(endZeroTouchControlPoint.y - zeroFreezePoint.y);
69
+ // ---------- 使用transform之前的坐标计算出新的width和height ----------
70
+ if (freezeWidth) {
71
+ // 理论计算出来的width应该等于oldWidth
72
+ // 但是有误差,比如oldWidth = 100; newWidth=100.000000000001
73
+ // 会在handleResize()限制放大缩小的最大最小范围中被阻止滑动
74
+ width = oldWidth;
75
+ }
76
+ if (freezeHeight) {
77
+ height = oldHeight;
78
+ }
79
+ return {
80
+ width: width,
81
+ height: height,
82
+ center: newCenter,
83
+ };
84
+ }
85
+ exports.calculateWidthAndHeight = calculateWidthAndHeight;
8
86
  function recalcRotatedResizeInfo(pct, resizeInfo, rotate, controlX, controlY, oldCenterX, oldCenterY, freezeWidth, freezeHeight) {
9
87
  if (freezeWidth === void 0) { freezeWidth = false; }
10
88
  if (freezeHeight === void 0) { freezeHeight = false; }
@@ -42,11 +120,12 @@ function recalcRotatedResizeInfo(pct, resizeInfo, rotate, controlX, controlY, ol
42
120
  * @param freezeWidth
43
121
  * @param freezeHeight
44
122
  */
45
- var recalcResizeInfo = function (index, resizeInfo, pct, freezeWidth, freezeHeight, rotate, controlX, controlY, oldCenterX, oldCenterY) {
123
+ var recalcResizeInfo = function (index, resizeInfo, pct, freezeWidth, freezeHeight, rotate, controlX, controlY, oldCenterX, oldCenterY, forceProportional) {
46
124
  if (pct === void 0) { pct = 1; }
47
125
  if (freezeWidth === void 0) { freezeWidth = false; }
48
126
  if (freezeHeight === void 0) { freezeHeight = false; }
49
127
  if (rotate === void 0) { rotate = 0; }
128
+ if (forceProportional === void 0) { forceProportional = false; }
50
129
  var nextResizeInfo = (0, lodash_es_1.cloneDeep)(resizeInfo);
51
130
  var deltaX = nextResizeInfo.deltaX, deltaY = nextResizeInfo.deltaY;
52
131
  var width = nextResizeInfo.width, height = nextResizeInfo.height, PCTResizeInfo = nextResizeInfo.PCTResizeInfo;
@@ -112,7 +191,84 @@ var recalcResizeInfo = function (index, resizeInfo, pct, freezeWidth, freezeHeig
112
191
  // 角度rotate不为0得到的resizeInfo.deltaX仅仅代表中心点的变化,而不是宽度的变化
113
192
  return recalcRotatedResizeInfo(pct, nextResizeInfo, rotate, controlX, controlY, oldCenterX, oldCenterY, freezeWidth, freezeHeight);
114
193
  }
115
- // 如果限制了宽/高不变,对应的 width/height 保持一致
194
+ //Shift键等比缩放逻辑
195
+ if (forceProportional) {
196
+ // 计算当前的宽高比
197
+ var aspectRatio = width / height;
198
+ // 根据拖拽方向确定主要的缩放参考
199
+ var primaryDelta = 0;
200
+ var newWidth = width;
201
+ var newHeight = height;
202
+ switch (index) {
203
+ case Control_1.ResizeControlIndex.LEFT_TOP:
204
+ // 取绝对值较大的delta作为主要缩放参考
205
+ primaryDelta = Math.abs(deltaX) > Math.abs(deltaY) ? -deltaX : -deltaY;
206
+ if (aspectRatio >= 1) {
207
+ // 宽度大于等于高度,以宽度为基准
208
+ newWidth = width + primaryDelta;
209
+ newHeight = newWidth / aspectRatio;
210
+ }
211
+ else {
212
+ // 高度大于宽度,以高度为基准
213
+ newHeight = height + primaryDelta;
214
+ newWidth = newHeight * aspectRatio;
215
+ }
216
+ nextResizeInfo.width = newWidth;
217
+ nextResizeInfo.height = newHeight;
218
+ nextResizeInfo.deltaX = width - newWidth;
219
+ nextResizeInfo.deltaY = height - newHeight;
220
+ break;
221
+ case Control_1.ResizeControlIndex.RIGHT_TOP:
222
+ primaryDelta = Math.abs(deltaX) > Math.abs(deltaY) ? deltaX : -deltaY;
223
+ if (aspectRatio >= 1) {
224
+ newWidth = width + primaryDelta;
225
+ newHeight = newWidth / aspectRatio;
226
+ }
227
+ else {
228
+ newHeight = height - primaryDelta;
229
+ newWidth = newHeight * aspectRatio;
230
+ }
231
+ nextResizeInfo.width = newWidth;
232
+ nextResizeInfo.height = newHeight;
233
+ nextResizeInfo.deltaX = newWidth - width;
234
+ nextResizeInfo.deltaY = height - newHeight;
235
+ break;
236
+ case Control_1.ResizeControlIndex.RIGHT_BOTTOM:
237
+ primaryDelta = Math.abs(deltaX) > Math.abs(deltaY) ? deltaX : deltaY;
238
+ if (aspectRatio >= 1) {
239
+ newWidth = width + primaryDelta;
240
+ newHeight = newWidth / aspectRatio;
241
+ }
242
+ else {
243
+ newHeight = height + primaryDelta;
244
+ newWidth = newHeight * aspectRatio;
245
+ }
246
+ nextResizeInfo.width = newWidth;
247
+ nextResizeInfo.height = newHeight;
248
+ nextResizeInfo.deltaX = newWidth - width;
249
+ nextResizeInfo.deltaY = newHeight - height;
250
+ break;
251
+ case Control_1.ResizeControlIndex.LEFT_BOTTOM:
252
+ primaryDelta = Math.abs(deltaX) > Math.abs(deltaY) ? -deltaX : deltaY;
253
+ if (aspectRatio >= 1) {
254
+ newWidth = width - primaryDelta;
255
+ newHeight = newWidth / aspectRatio;
256
+ }
257
+ else {
258
+ newHeight = height + primaryDelta;
259
+ newWidth = newHeight * aspectRatio;
260
+ }
261
+ nextResizeInfo.width = newWidth;
262
+ nextResizeInfo.height = newHeight;
263
+ nextResizeInfo.deltaX = width - newWidth;
264
+ nextResizeInfo.deltaY = newHeight - height;
265
+ break;
266
+ default:
267
+ break;
268
+ }
269
+ return nextResizeInfo;
270
+ }
271
+ // 原有的非等比缩放逻辑保持不变
116
272
  switch (index) {
117
273
  case Control_1.ResizeControlIndex.LEFT_TOP:
118
274
  nextResizeInfo.width = freezeWidth ? width : width - deltaX * pct;
@@ -195,9 +351,10 @@ exports.triggerResizeEvent = triggerResizeEvent;
195
351
  * @param nodeModel
196
352
  * @param graphModel
197
353
  * @param cancelCallback
354
+ * @param forceProportional
198
355
  */
199
356
  var handleResize = function (_a) {
200
- var x = _a.x, y = _a.y, deltaX = _a.deltaX, deltaY = _a.deltaY, index = _a.index, nodeModel = _a.nodeModel, graphModel = _a.graphModel, cancelCallback = _a.cancelCallback;
357
+ var x = _a.x, y = _a.y, deltaX = _a.deltaX, deltaY = _a.deltaY, index = _a.index, nodeModel = _a.nodeModel, graphModel = _a.graphModel, cancelCallback = _a.cancelCallback, _b = _a.forceProportional, forceProportional = _b === void 0 ? false : _b;
201
358
  var r = nodeModel.r, // circle
202
359
  rx = nodeModel.rx, // ellipse/diamond
203
360
  ry = nodeModel.ry, width = nodeModel.width, // rect/html
@@ -214,7 +371,7 @@ var handleResize = function (_a) {
214
371
  var pct = r || (rx && ry) ? 1 / 2 : 1;
215
372
  var controlX = x;
216
373
  var controlY = y;
217
- var nextSize = (0, exports.recalcResizeInfo)(index, resizeInfo, pct, isFreezeWidth, isFreezeHeight, rotate, controlX, controlY, oldCenterX, oldCenterY);
374
+ var nextSize = (0, exports.recalcResizeInfo)(index, resizeInfo, pct, isFreezeWidth, isFreezeHeight, rotate, controlX, controlY, oldCenterX, oldCenterY, forceProportional);
218
375
  // 限制放大缩小的最大最小范围
219
376
  if (nextSize.width < minWidth ||
220
377
  nextSize.width > maxWidth ||
@@ -247,81 +404,3 @@ var handleResize = function (_a) {
247
404
  (0, exports.triggerResizeEvent)(preNodeData, curNodeData, deltaX, deltaY, index, nodeModel, graphModel);
248
405
  };
249
406
  exports.handleResize = handleResize;
250
- function calculateWidthAndHeight(startRotatedTouchControlPoint, endRotatedTouchControlPoint, oldCenter, angle, freezeWidth, freezeHeight, oldWidth, oldHeight) {
251
- if (freezeWidth === void 0) { freezeWidth = false; }
252
- if (freezeHeight === void 0) { freezeHeight = false; }
253
- // 假设目前触摸的是右下角的control点
254
- // 计算出来左上角的control坐标,resize过程左上角的control坐标保持不变
255
- var freezePoint = {
256
- x: oldCenter.x - (startRotatedTouchControlPoint.x - oldCenter.x),
257
- y: oldCenter.y - (startRotatedTouchControlPoint.y - oldCenter.y),
258
- };
259
- // 【touchEndPoint】右下角 + freezePoint左上角 计算出新的中心点
260
- var newCenter = (0, rotate_1.getNewCenter)(freezePoint, endRotatedTouchControlPoint);
261
- // 得到【touchEndPoint】右下角-没有transform的坐标
262
- var endZeroTouchControlPoint = (0, rotate_1.calculatePointAfterRotateAngle)(endRotatedTouchControlPoint, newCenter, -angle);
263
- // ---------- 使用transform之前的坐标计算出新的width和height ----------
264
- // 得到左上角---没有transform的坐标
265
- var zeroFreezePoint = (0, rotate_1.calculatePointAfterRotateAngle)(freezePoint, newCenter, -angle);
266
- if (freezeWidth) {
267
- // 如果固定width,那么不能单纯使用endZeroTouchControlPoint.x=startZeroTouchControlPoint.x
268
- // 因为去掉transform的左上角不一定是重合的,我们要保证的是transform后的左上角重合
269
- var newWidth = Math.abs(endZeroTouchControlPoint.x - zeroFreezePoint.x);
270
- var widthDx = newWidth - oldWidth;
271
- // 点击的是左边锚点,是+widthDx/2,点击是右边锚点,是-widthDx/2
272
- if (newCenter.x > endZeroTouchControlPoint.x) {
273
- // 当前触摸的是左边锚点
274
- newCenter.x = newCenter.x + widthDx / 2;
275
- }
276
- else {
277
- // 当前触摸的是右边锚点
278
- newCenter.x = newCenter.x - widthDx / 2;
279
- }
280
- }
281
- if (freezeHeight) {
282
- var newHeight = Math.abs(endZeroTouchControlPoint.y - zeroFreezePoint.y);
283
- var heightDy = newHeight - oldHeight;
284
- if (newCenter.y > endZeroTouchControlPoint.y) {
285
- // 当前触摸的是上边锚点
286
- newCenter.y = newCenter.y + heightDy / 2;
287
- }
288
- else {
289
- newCenter.y = newCenter.y - heightDy / 2;
290
- }
291
- }
292
- if (freezeWidth || freezeHeight) {
293
- // 如果调整过transform之前的坐标,那么transform后的坐标也会改变,那么算出来的newCenter也得调整
294
- // 由于无论如何rotate,中心点都是不变的,因此我们可以使用transform之前的坐标算出新的中心点
295
- var nowFreezePoint = (0, rotate_1.calculatePointAfterRotateAngle)(zeroFreezePoint, newCenter, angle);
296
- // 得到当前新rect的左上角与实际上transform后的左上角的偏移量
297
- var dx = nowFreezePoint.x - freezePoint.x;
298
- var dy = nowFreezePoint.y - freezePoint.y;
299
- // 修正不使用transform的坐标: 左上角、右下角、center
300
- newCenter.x = newCenter.x - dx;
301
- newCenter.y = newCenter.y - dy;
302
- zeroFreezePoint = (0, rotate_1.calculatePointAfterRotateAngle)(freezePoint, newCenter, -angle);
303
- endZeroTouchControlPoint = {
304
- x: newCenter.x - (zeroFreezePoint.x - newCenter.x),
305
- y: newCenter.y - (zeroFreezePoint.y - newCenter.y),
306
- };
307
- }
308
- // transform之前的坐标的左上角+右下角计算出宽度和高度
309
- var width = Math.abs(endZeroTouchControlPoint.x - zeroFreezePoint.x);
310
- var height = Math.abs(endZeroTouchControlPoint.y - zeroFreezePoint.y);
311
- // ---------- 使用transform之前的坐标计算出新的width和height ----------
312
- if (freezeWidth) {
313
- // 理论计算出来的width应该等于oldWidth
314
- // 但是有误差,比如oldWidth = 100; newWidth=100.000000000001
315
- // 会在handleResize()限制放大缩小的最大最小范围中被阻止滑动
316
- width = oldWidth;
317
- }
318
- if (freezeHeight) {
319
- height = oldHeight;
320
- }
321
- return {
322
- width: width,
323
- height: height,
324
- center: newCenter,
325
- };
326
- }
327
- exports.calculateWidthAndHeight = calculateWidthAndHeight;
@@ -4,8 +4,8 @@ import { IDragParams, StepDrag } from '../util';
4
4
  import { BaseNodeModel, GraphModel } from '../model';
5
5
  import NodeData = LogicFlow.NodeData;
6
6
  import VectorData = LogicFlow.VectorData;
7
- import ResizeInfo = ResizeControl.ResizeInfo;
8
7
  import ResizeNodeData = ResizeControl.ResizeNodeData;
8
+ import ResizeInfo = ResizeControl.ResizeInfo;
9
9
  import ControlItemProps = ResizeControl.ControlItemProps;
10
10
  export declare enum ResizeControlIndex {
11
11
  LEFT_TOP = 0,
@@ -29,7 +29,11 @@ export declare class ResizeControl extends Component<IResizeControlProps, IResiz
29
29
  readonly nodeModel: BaseNodeModel;
30
30
  readonly graphModel: GraphModel;
31
31
  readonly dragHandler: StepDrag;
32
+ private isShiftPressed;
32
33
  constructor(props: IResizeControlProps);
34
+ bindKeyboardEvents: () => void;
35
+ handleKeyDown: (event: KeyboardEvent) => void;
36
+ handleKeyUp: (event: KeyboardEvent) => void;
33
37
  componentWillUnmount(): void;
34
38
  updateEdgePointByAnchors: () => void;
35
39
  triggerResizeEvent: (preNodeData: ResizeNodeData, curNodeData: ResizeNodeData, deltaX: any, deltaY: any, index: any, nodeModel: BaseNodeModel) => void;
@@ -71,6 +71,24 @@ var ResizeControl = /** @class */ (function (_super) {
71
71
  __extends(ResizeControl, _super);
72
72
  function ResizeControl(props) {
73
73
  var _this = _super.call(this) || this;
74
+ //判断Shift键状态
75
+ _this.isShiftPressed = false;
76
+ //绑定键盘事件监听
77
+ _this.bindKeyboardEvents = function () {
78
+ document.addEventListener('keydown', _this.handleKeyDown);
79
+ document.addEventListener('keyup', _this.handleKeyUp);
80
+ };
81
+ //处理键盘按下事件
82
+ _this.handleKeyDown = function (event) {
83
+ if (event.key === 'Shift') {
84
+ _this.isShiftPressed = true;
85
+ }
86
+ };
87
+ _this.handleKeyUp = function (event) {
88
+ if (event.key === 'Shift') {
89
+ _this.isShiftPressed = false;
90
+ }
91
+ };
74
92
  _this.updateEdgePointByAnchors = function () {
75
93
  // https://github.com/didi/LogicFlow/issues/807
76
94
  // https://github.com/didi/LogicFlow/issues/875
@@ -223,6 +241,7 @@ var ResizeControl = /** @class */ (function (_super) {
223
241
  index: index,
224
242
  nodeModel: model,
225
243
  graphModel: graphModel,
244
+ forceProportional: _this.isShiftPressed,
226
245
  cancelCallback: function () {
227
246
  _this.dragHandler.cancelDrag();
228
247
  },
@@ -313,17 +332,19 @@ var ResizeControl = /** @class */ (function (_super) {
313
332
  _this.index = index;
314
333
  _this.nodeModel = model;
315
334
  _this.graphModel = graphModel;
316
- // 初始化拖拽工具
317
335
  _this.dragHandler = new util_1.StepDrag({
318
336
  onDragStart: _this.onDragStart,
319
337
  onDragging: _this.onDragging,
320
338
  onDragEnd: _this.onDragEnd,
321
339
  step: graphModel.gridSize,
322
340
  });
341
+ _this.bindKeyboardEvents();
323
342
  return _this;
324
343
  }
325
344
  ResizeControl.prototype.componentWillUnmount = function () {
326
345
  this.dragHandler.destroy();
346
+ document.removeEventListener('keydown', this.handleKeyDown);
347
+ document.removeEventListener('keyup', this.handleKeyUp);
327
348
  };
328
349
  ResizeControl.prototype.render = function () {
329
350
  var _a = this.props, x = _a.x, y = _a.y, direction = _a.direction, model = _a.model;
@@ -33,6 +33,9 @@ var Dnd = /** @class */ (function () {
33
33
  })));
34
34
  };
35
35
  this.onDragOver = function (e) {
36
+ _this.lf.graphModel.eventCenter.emit(constant_1.EventType.BLANK_CANVAS_MOUSEMOVE, {
37
+ e: e,
38
+ });
36
39
  e.preventDefault();
37
40
  if (_this.fakeNode) {
38
41
  var _a = _this.clientToLocalPoint({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@logicflow/core",
3
- "version": "2.0.16",
3
+ "version": "2.1.1",
4
4
  "description": "LogicFlow, help you quickly create flowcharts",
5
5
  "main": "lib/index.js",
6
6
  "module": "es/index.js",
package/src/LogicFlow.tsx CHANGED
@@ -133,7 +133,10 @@ export class LogicFlow {
133
133
  })
134
134
 
135
135
  if (initOptions.snapline !== false) {
136
- this.snaplineModel = new SnaplineModel(this.graphModel)
136
+ this.snaplineModel = new SnaplineModel(
137
+ this.graphModel,
138
+ initOptions.snaplineEpsilon,
139
+ )
137
140
  snapline(eventCenter, this.snaplineModel)
138
141
  }
139
142
  if (!initOptions.isSilentMode) {
@@ -900,7 +903,6 @@ export class LogicFlow {
900
903
  updateEditConfig(config: Partial<IEditConfigType>) {
901
904
  const { editConfigModel, transformModel } = this.graphModel
902
905
  const currentSnapGrid = editConfigModel.snapGrid
903
-
904
906
  editConfigModel.updateEditConfig(config)
905
907
  if (config?.stopMoveGraph !== undefined) {
906
908
  transformModel.updateTranslateLimits(config.stopMoveGraph)
@@ -916,6 +918,9 @@ export class LogicFlow {
916
918
  } = this.graphModel
917
919
  this.graphModel.updateGridSize(config.snapGrid ? size : 1)
918
920
  }
921
+ this.emit(EventType.EDIT_CONFIG_CHANGED, {
922
+ data: editConfigModel.getConfig(),
923
+ })
919
924
  }
920
925
 
921
926
  /**
@@ -101,6 +101,7 @@ export enum EventType {
101
101
  BLANK_DRAG = 'blank:drag',
102
102
  BLANK_DROP = 'blank:drop',
103
103
  BLANK_MOUSEMOVE = 'blank:mousemove',
104
+ BLANK_CANVAS_MOUSEMOVE = 'blank:canvas-mousemove',
104
105
  BLANK_MOUSEUP = 'blank:mouseup',
105
106
  BLANK_CLICK = 'blank:click',
106
107
  BLANK_CONTEXTMENU = 'blank:contextmenu',
@@ -157,6 +158,7 @@ export enum EventType {
157
158
  GRAPH_TRANSFORM = 'graph:transform',
158
159
  GRAPH_RENDERED = 'graph:rendered',
159
160
  GRAPH_UPDATED = 'graph:updated',
161
+ EDIT_CONFIG_CHANGED = 'editConfig:changed',
160
162
  }
161
163
 
162
164
  export enum OverlapMode {
@@ -19,6 +19,12 @@ export function translateNodeData(nodeData: NodeData, distance: number) {
19
19
  nodeData.text.y += distance
20
20
  }
21
21
 
22
+ if (!isEmpty(nodeData.properties?._label)) {
23
+ nodeData.properties?._label.forEach((label) => {
24
+ label.x += distance
25
+ label.y += distance
26
+ })
27
+ }
22
28
  return nodeData
23
29
  }
24
30
 
@@ -984,6 +984,8 @@ export class GraphModel {
984
984
  }
985
985
  if (edgeOriginData.id && this.edgesMap[edgeOriginData.id]) {
986
986
  delete edgeOriginData.id
987
+ delete edgeOriginData.sourceAnchorId
988
+ delete edgeOriginData.targetAnchorId
987
989
  }
988
990
  const Model = this.getModel(type) as BaseEdgeModelCtor
989
991
  if (!Model) {