@logicflow/core 2.0.9 → 2.0.10

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 (77) hide show
  1. package/.turbo/turbo-build$colon$dev.log +2 -2
  2. package/.turbo/turbo-build.log +6 -6
  3. package/CHANGELOG.md +16 -0
  4. package/dist/index.min.js +1 -1
  5. package/dist/index.min.js.map +1 -1
  6. package/es/LogicFlow.js +14 -1
  7. package/es/event/eventEmitter.d.ts +1 -0
  8. package/es/event/eventEmitter.js +3 -0
  9. package/es/history/index.d.ts +1 -0
  10. package/es/history/index.js +6 -0
  11. package/es/keyboard/index.d.ts +1 -0
  12. package/es/keyboard/index.js +3 -0
  13. package/es/model/EditConfigModel.d.ts +3 -1
  14. package/es/model/EditConfigModel.js +5 -0
  15. package/es/model/GraphModel.d.ts +13 -1
  16. package/es/model/GraphModel.js +41 -41
  17. package/es/model/edge/BaseEdgeModel.js +6 -3
  18. package/es/model/edge/PolylineEdgeModel.d.ts +1 -0
  19. package/es/model/edge/PolylineEdgeModel.js +7 -0
  20. package/es/model/node/BaseNodeModel.js +3 -2
  21. package/es/tool/index.d.ts +1 -0
  22. package/es/tool/index.js +4 -0
  23. package/es/util/geometry.d.ts +1 -1
  24. package/es/util/geometry.js +4 -1
  25. package/es/view/Graph.js +19 -2
  26. package/es/view/behavior/dnd.js +3 -2
  27. package/es/view/edge/BaseEdge.js +9 -2
  28. package/es/view/node/BaseNode.js +19 -6
  29. package/es/view/node/HtmlNode.js +1 -0
  30. package/es/view/overlay/CanvasOverlay.js +6 -4
  31. package/es/view/text/BaseText.js +1 -0
  32. package/lib/LogicFlow.js +13 -0
  33. package/lib/event/eventEmitter.d.ts +1 -0
  34. package/lib/event/eventEmitter.js +3 -0
  35. package/lib/history/index.d.ts +1 -0
  36. package/lib/history/index.js +6 -0
  37. package/lib/keyboard/index.d.ts +1 -0
  38. package/lib/keyboard/index.js +3 -0
  39. package/lib/model/EditConfigModel.d.ts +3 -1
  40. package/lib/model/EditConfigModel.js +5 -0
  41. package/lib/model/GraphModel.d.ts +13 -1
  42. package/lib/model/GraphModel.js +40 -40
  43. package/lib/model/edge/BaseEdgeModel.js +6 -3
  44. package/lib/model/edge/PolylineEdgeModel.d.ts +1 -0
  45. package/lib/model/edge/PolylineEdgeModel.js +7 -0
  46. package/lib/model/node/BaseNodeModel.js +3 -2
  47. package/lib/tool/index.d.ts +1 -0
  48. package/lib/tool/index.js +4 -0
  49. package/lib/util/geometry.d.ts +1 -1
  50. package/lib/util/geometry.js +4 -1
  51. package/lib/view/Graph.js +19 -2
  52. package/lib/view/behavior/dnd.js +3 -2
  53. package/lib/view/edge/BaseEdge.js +9 -2
  54. package/lib/view/node/BaseNode.js +19 -6
  55. package/lib/view/node/HtmlNode.js +1 -0
  56. package/lib/view/overlay/CanvasOverlay.js +6 -4
  57. package/lib/view/text/BaseText.js +1 -0
  58. package/package.json +1 -1
  59. package/src/LogicFlow.tsx +19 -1
  60. package/src/event/eventEmitter.ts +4 -0
  61. package/src/history/index.ts +7 -0
  62. package/src/keyboard/index.ts +4 -0
  63. package/src/model/EditConfigModel.ts +4 -0
  64. package/src/model/GraphModel.ts +62 -70
  65. package/src/model/edge/BaseEdgeModel.ts +7 -2
  66. package/src/model/edge/PolylineEdgeModel.ts +8 -0
  67. package/src/model/node/BaseNodeModel.ts +5 -2
  68. package/src/tool/index.ts +5 -0
  69. package/src/util/geometry.ts +3 -1
  70. package/src/view/Graph.tsx +19 -2
  71. package/src/view/behavior/dnd.ts +5 -2
  72. package/src/view/edge/BaseEdge.tsx +9 -2
  73. package/src/view/node/BaseNode.tsx +20 -6
  74. package/src/view/node/HtmlNode.tsx +1 -0
  75. package/src/view/overlay/CanvasOverlay.tsx +6 -5
  76. package/src/view/text/BaseText.tsx +1 -0
  77. package/stats.html +1 -1
@@ -89,7 +89,7 @@ var BaseNode = /** @class */ (function (_super) {
89
89
  var _b, _c, _d, _e;
90
90
  var event = _a.event;
91
91
  var _f = _this.props, model = _f.model, graphModel = _f.graphModel;
92
- var _g = graphModel.editConfigModel, stopMoveGraph = _g.stopMoveGraph, autoExpand = _g.autoExpand, transformModel = graphModel.transformModel, selectNodes = graphModel.selectNodes, width = graphModel.width, height = graphModel.height, gridSize = graphModel.gridSize;
92
+ var _g = graphModel.editConfigModel, stopMoveGraph = _g.stopMoveGraph, autoExpand = _g.autoExpand, snapGrid = _g.snapGrid, transformModel = graphModel.transformModel, selectNodes = graphModel.selectNodes, width = graphModel.width, height = graphModel.height, gridSize = graphModel.gridSize;
93
93
  model.isDragging = true;
94
94
  var _h = event, clientX = _h.clientX, clientY = _h.clientY;
95
95
  var _j = graphModel.getPointByClient({
@@ -101,9 +101,9 @@ var BaseNode = /** @class */ (function (_super) {
101
101
  // 2. 考虑鼠标位置不再节点中心
102
102
  x = x + ((_c = (_b = _this.moveOffset) === null || _b === void 0 ? void 0 : _b.dx) !== null && _c !== void 0 ? _c : 0);
103
103
  y = y + ((_e = (_d = _this.moveOffset) === null || _d === void 0 ? void 0 : _d.dy) !== null && _e !== void 0 ? _e : 0);
104
- // 将x, y移动到grid上
105
- x = (0, util_1.snapToGrid)(x, gridSize);
106
- y = (0, util_1.snapToGrid)(y, gridSize);
104
+ // 校准坐标
105
+ x = (0, util_1.snapToGrid)(x, gridSize, snapGrid);
106
+ y = (0, util_1.snapToGrid)(y, gridSize, snapGrid);
107
107
  if (!width || !height) {
108
108
  graphModel.moveNode2Coordinate(model.id, x, y);
109
109
  return;
@@ -217,7 +217,10 @@ var BaseNode = /** @class */ (function (_super) {
217
217
  else {
218
218
  graphModel.selectNodeById(model.id, isMultiple);
219
219
  eventOptions.isSelected = true;
220
- _this.toFront();
220
+ // 静默模式下点击节点不变更节点层级
221
+ if (!editConfigModel.isSilentMode) {
222
+ _this.toFront();
223
+ }
221
224
  }
222
225
  // 不是双击的,默认都是单击
223
226
  if (isDoubleClick) {
@@ -237,6 +240,7 @@ var BaseNode = /** @class */ (function (_super) {
237
240
  _this.handleContextMenu = function (ev) {
238
241
  ev.preventDefault();
239
242
  var _a = _this.props, model = _a.model, graphModel = _a.graphModel;
243
+ var editConfigModel = graphModel.editConfigModel;
240
244
  // 节点数据,多为事件对象数据抛出
241
245
  var nodeData = model.getData();
242
246
  var position = graphModel.getPointByClient({
@@ -252,7 +256,10 @@ var BaseNode = /** @class */ (function (_super) {
252
256
  e: ev,
253
257
  position: position,
254
258
  });
255
- _this.toFront();
259
+ // 静默模式下点击节点不变更节点层级
260
+ if (!editConfigModel.isSilentMode) {
261
+ _this.toFront();
262
+ }
256
263
  };
257
264
  _this.handleMouseDown = function (ev) {
258
265
  var _a = _this.props, model = _a.model, graphModel = _a.graphModel;
@@ -326,6 +333,12 @@ var BaseNode = /** @class */ (function (_super) {
326
333
  if (this.modelDisposer) {
327
334
  this.modelDisposer();
328
335
  }
336
+ // 以下是 mobx-preact 中 componentWillUnmount 的回调逻辑,但是不知道出于什么考虑,mobx-preact 没有混入这一段逻辑
337
+ // @ts-ignore
338
+ if (this.render.$mobx) {
339
+ // @ts-ignore
340
+ this.render.$mobx.dispose();
341
+ }
329
342
  };
330
343
  BaseNode.prototype.componentDidMount = function () { };
331
344
  BaseNode.prototype.componentDidUpdate = function () { };
@@ -119,6 +119,7 @@ var HtmlNode = /** @class */ (function (_super) {
119
119
  }
120
120
  };
121
121
  HtmlNode.prototype.componentWillUnmount = function () {
122
+ _super.prototype.componentWillUnmount.call(this);
122
123
  this.rootEl.innerHTML = '';
123
124
  };
124
125
  HtmlNode.prototype.getShape = function () {
@@ -66,8 +66,9 @@ var CanvasOverlay = /** @class */ (function (_super) {
66
66
  _this.zoomHandler = function (ev) {
67
67
  var _a = _this.props, _b = _a.graphModel, editConfigModel = _b.editConfigModel, transformModel = _b.transformModel, gridSize = _b.gridSize, graphModel = _a.graphModel;
68
68
  var eX = ev.deltaX, eY = ev.deltaY;
69
+ var stopScrollGraph = editConfigModel.stopScrollGraph, stopZoomGraph = editConfigModel.stopZoomGraph;
69
70
  // 如果没有禁止滚动移动画布, 并且当前触发的时候ctrl键、cmd键没有按住, 那么移动画布
70
- if (!editConfigModel.stopScrollGraph && !ev.ctrlKey && !ev.metaKey) {
71
+ if (!stopScrollGraph && !ev.ctrlKey && !ev.metaKey) {
71
72
  ev.preventDefault();
72
73
  _this.stepScrollX += eX;
73
74
  _this.stepScrollY += eY;
@@ -86,7 +87,7 @@ var CanvasOverlay = /** @class */ (function (_super) {
86
87
  return;
87
88
  }
88
89
  // 如果没有禁止缩放画布,那么进行缩放. 在禁止缩放画布后,按住 ctrl、cmd 键也不能缩放了。
89
- if (!editConfigModel.stopZoomGraph) {
90
+ if (!stopZoomGraph) {
90
91
  ev.preventDefault();
91
92
  var position = graphModel.getPointByClient({
92
93
  x: ev.clientX,
@@ -127,10 +128,11 @@ var CanvasOverlay = /** @class */ (function (_super) {
127
128
  // 鼠标、触摸板 按下
128
129
  _this.mouseDownHandler = function (ev) {
129
130
  var _a = _this.props.graphModel, eventCenter = _a.eventCenter, editConfigModel = _a.editConfigModel, SCALE_X = _a.transformModel.SCALE_X, gridSize = _a.gridSize;
131
+ var adjustEdge = editConfigModel.adjustEdge, adjustNodePosition = editConfigModel.adjustNodePosition, stopMoveGraph = editConfigModel.stopMoveGraph;
130
132
  var target = ev.target;
131
- var isFrozenElement = !editConfigModel.adjustEdge && !editConfigModel.adjustNodePosition;
133
+ var isFrozenElement = !adjustEdge && !adjustNodePosition;
132
134
  if (target.getAttribute('name') === 'canvas-overlay' || isFrozenElement) {
133
- if (editConfigModel.stopMoveGraph !== true) {
135
+ if (stopMoveGraph !== true) {
134
136
  _this.stepDrag.setStep(gridSize * SCALE_X);
135
137
  _this.stepDrag.handleMouseDown(ev);
136
138
  }
@@ -60,6 +60,7 @@ var BaseText = /** @class */ (function (_super) {
60
60
  var _a = _this.props, draggable = _a.draggable, model = _a.model, graphModel = _a.graphModel;
61
61
  var nodeTextDraggable = graphModel.editConfigModel.nodeTextDraggable;
62
62
  if (draggable !== null && draggable !== void 0 ? draggable : nodeTextDraggable) {
63
+ e.stopPropagation();
63
64
  _this.stepperDrag.model = model;
64
65
  _this.stepperDrag.handleMouseDown(e);
65
66
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@logicflow/core",
3
- "version": "2.0.9",
3
+ "version": "2.0.10",
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
@@ -1,5 +1,5 @@
1
1
  import { ComponentType, createElement as h, render } from 'preact/compat'
2
- import { cloneDeep, forEach, indexOf } from 'lodash-es'
2
+ import { cloneDeep, forEach, indexOf, isNil } from 'lodash-es'
3
3
  import { observer } from '.'
4
4
  import { Options as LFOptions } from './options'
5
5
  import * as _Model from './model'
@@ -885,12 +885,23 @@ export class LogicFlow {
885
885
  */
886
886
  updateEditConfig(config: Partial<IEditConfigType>) {
887
887
  const { editConfigModel, transformModel } = this.graphModel
888
+ const currentSnapGrid = editConfigModel.snapGrid
889
+
888
890
  editConfigModel.updateEditConfig(config)
889
891
  if (config?.stopMoveGraph !== undefined) {
890
892
  transformModel.updateTranslateLimits(config.stopMoveGraph)
891
893
  }
894
+
892
895
  // 静默模式切换时,修改快捷键的启用状态
893
896
  config?.isSilentMode ? this.keyboard.disable() : this.keyboard.enable(true)
897
+
898
+ // 切换网格对齐状态时,修改网格尺寸
899
+ if (!isNil(config?.snapGrid) && config.snapGrid !== currentSnapGrid) {
900
+ const {
901
+ grid: { size = 1 },
902
+ } = this.graphModel
903
+ this.graphModel.updateGridSize(config.snapGrid ? size : 1)
904
+ }
894
905
  }
895
906
 
896
907
  /**
@@ -1044,6 +1055,8 @@ export class LogicFlow {
1044
1055
  */
1045
1056
  clearData() {
1046
1057
  this.graphModel.clearData()
1058
+ // 强制刷新数据, 让 preact 清除对已删除节点的引用
1059
+ this.render({})
1047
1060
  }
1048
1061
 
1049
1062
  /*********************************************************
@@ -1372,7 +1385,12 @@ export class LogicFlow {
1372
1385
 
1373
1386
  /** 销毁当前实例 */
1374
1387
  destroy() {
1388
+ this.clearData()
1389
+ render(null, this.container)
1390
+ this.keyboard.destroy()
1375
1391
  this.graphModel.destroy()
1392
+ this.tool.destroy()
1393
+ this.history.destroy()
1376
1394
  }
1377
1395
  }
1378
1396
 
@@ -147,6 +147,10 @@ export default class EventEmitter {
147
147
  getEvents() {
148
148
  return this._events
149
149
  }
150
+
151
+ destroy() {
152
+ this._events = {}
153
+ }
150
154
  }
151
155
 
152
156
  export { EventEmitter, EventArgs }
@@ -107,6 +107,13 @@ export class History {
107
107
  }, this.waitTime),
108
108
  )
109
109
  }
110
+
111
+ destroy() {
112
+ this.undos = []
113
+ this.redos = []
114
+ this.curData = null
115
+ this.stopWatch && this.stopWatch()
116
+ }
110
117
  }
111
118
 
112
119
  export default History
@@ -90,6 +90,10 @@ export class Keyboard {
90
90
  }
91
91
  }
92
92
 
93
+ destroy() {
94
+ this.mousetrap.reset()
95
+ }
96
+
93
97
  private getKeys(keys: string | string[]) {
94
98
  return (Array.isArray(keys) ? keys : [keys]).map((key) =>
95
99
  this.formatKey(key),
@@ -123,6 +123,8 @@ export interface IEditConfigType {
123
123
  nodeTextMode: TextMode
124
124
  // 边文本类型
125
125
  edgeTextMode: TextMode
126
+ // 开启网格对齐
127
+ snapGrid: boolean
126
128
  }
127
129
 
128
130
  export type IConfigKeys = keyof IEditConfigType
@@ -154,6 +156,7 @@ const allKeys = [
154
156
  'stopZoomGraph', // 禁止缩放画布
155
157
  'stopScrollGraph', // 禁止鼠标滚动移动画布
156
158
  'stopMoveGraph', // 禁止拖动画布
159
+ 'snapGrid', // 是否开启网格对齐
157
160
  'adjustEdge', // 允许调整边
158
161
  'adjustEdgeMiddle', // 允许调整边中点
159
162
  'adjustEdgeStartAndEnd', // 允许调整边起点和终点
@@ -198,6 +201,7 @@ export class EditConfigModel {
198
201
  @observable stopZoomGraph = false
199
202
  @observable stopMoveGraph = false
200
203
  @observable stopScrollGraph = false
204
+ @observable snapGrid = false
201
205
  /*********************************************************
202
206
  * 文本相关配置(全局)
203
207
  ********************************************************/
@@ -1,4 +1,12 @@
1
- import { find, forEach, map, merge, isBoolean, debounce, isEqual } from 'lodash-es'
1
+ import {
2
+ find,
3
+ forEach,
4
+ map,
5
+ merge,
6
+ isBoolean,
7
+ debounce,
8
+ isNil,
9
+ } from 'lodash-es'
2
10
  import { action, computed, observable } from 'mobx'
3
11
  import {
4
12
  BaseEdgeModel,
@@ -41,7 +49,6 @@ import Position = LogicFlow.Position
41
49
  import PointTuple = LogicFlow.PointTuple
42
50
  import GraphData = LogicFlow.GraphData
43
51
  import NodeConfig = LogicFlow.NodeConfig
44
- import AnchorConfig = Model.AnchorConfig
45
52
  import BaseNodeModelCtor = LogicFlow.BaseNodeModelCtor
46
53
  import BaseEdgeModelCtor = LogicFlow.BaseEdgeModelCtor
47
54
 
@@ -99,6 +106,15 @@ export class GraphModel {
99
106
  */
100
107
  customTrajectory: LFOptions.Definition['customTrajectory']
101
108
 
109
+ /**
110
+ * 判断是否使用的是容器的宽度
111
+ */
112
+ isContainerWidth: boolean
113
+ /**
114
+ * 判断是否使用的是容器的高度
115
+ */
116
+ isContainerHeight: boolean
117
+
102
118
  // 在图上操作创建边时,默认使用的边类型.
103
119
  @observable edgeType: string
104
120
  // 当前图上所有节点的model
@@ -144,7 +160,9 @@ export class GraphModel {
144
160
  this.rootEl = container
145
161
  this.partial = !!partial
146
162
  this.background = background
147
- if (typeof grid === 'object') {
163
+ if (typeof grid === 'object' && options.snapGrid) {
164
+ // 开启网格对齐时才根据网格尺寸设置步长
165
+ // TODO:需要让用户设置成 0 吗?后面可以讨论一下
148
166
  this.gridSize = grid.size || 1 // 默认 gridSize 设置为 1
149
167
  }
150
168
  this.theme = setupTheme(options.style)
@@ -153,8 +171,10 @@ export class GraphModel {
153
171
  this.animation = setupAnimation(animation)
154
172
  this.overlapMode = options.overlapMode || OverlapMode.DEFAULT
155
173
 
156
- this.width = options.width || this.rootEl.getBoundingClientRect().width
157
- this.height = options.height || this.rootEl.getBoundingClientRect().height
174
+ this.width = options.width ?? this.rootEl.getBoundingClientRect().width
175
+ this.isContainerWidth = isNil(options.width)
176
+ this.height = options.height ?? this.rootEl.getBoundingClientRect().height
177
+ this.isContainerHeight = isNil(options.height)
158
178
 
159
179
  const resizeObserver = new ResizeObserver(
160
180
  debounce(
@@ -438,18 +458,25 @@ export class GraphModel {
438
458
  * @param { object } graphData 图数据
439
459
  */
440
460
  graphDataToModel(graphData: Partial<LogicFlow.GraphConfigData>) {
441
- if (!this.width || !this.height) {
442
- this.resize()
443
- }
461
+ // 宽度必然存在,取消重新计算
462
+ // if (!this.width || !this.height) {
463
+ // this.resize()
464
+ // }
444
465
  if (!graphData) {
445
- this.nodes = []
446
- this.edges = []
466
+ this.clearData()
447
467
  return
448
468
  }
469
+ this.elementsModelMap.clear()
470
+ this.nodeModelMap.clear()
471
+ this.edgeModelMap.clear()
472
+
449
473
  if (graphData.nodes) {
450
- this.nodes = map(graphData.nodes, (node: NodeConfig) =>
451
- this.getModelAfterSnapToGrid(node),
452
- )
474
+ this.nodes = map(graphData.nodes, (node: NodeConfig) => {
475
+ const nodeModel = this.getModelAfterSnapToGrid(node)
476
+ this.elementsModelMap.set(nodeModel.id, nodeModel)
477
+ this.nodeModelMap.set(nodeModel.id, nodeModel)
478
+ return nodeModel
479
+ })
453
480
  } else {
454
481
  this.nodes = []
455
482
  }
@@ -463,58 +490,6 @@ export class GraphModel {
463
490
  throw new Error(`找不到${edge.type}对应的边。`)
464
491
  }
465
492
  const edgeModel = new Model(edge, this)
466
- // 根据edgeModel中存储的数据找到当前画布上的起终锚点坐标
467
- // 判断当前起终锚点数据和Model中存储的起终点数据是否一致,不一致更新起终点信息
468
- const {
469
- sourceNodeId,
470
- targetNodeId,
471
- sourceAnchorId = '',
472
- targetAnchorId = '',
473
- startPoint,
474
- endPoint,
475
- text,
476
- textPosition,
477
- } = edgeModel
478
- const updateAnchorPoint = (
479
- node: BaseNodeModel | undefined,
480
- anchorId: string,
481
- point: Position,
482
- updatePoint: (anchor: AnchorConfig) => void,
483
- ) => {
484
- const anchor = node?.anchors.find((anchor) => anchor.id === anchorId)
485
- if (anchor && !isEqual(anchor, point)) {
486
- updatePoint(anchor)
487
- }
488
- }
489
-
490
- const sourceNode = this.getNodeModelById(sourceNodeId)
491
- const targetNode = this.getNodeModelById(targetNodeId)
492
-
493
- updateAnchorPoint(
494
- sourceNode,
495
- sourceAnchorId,
496
- startPoint,
497
- edgeModel.updateStartPoint.bind(edgeModel),
498
- )
499
- updateAnchorPoint(
500
- targetNode,
501
- targetAnchorId,
502
- endPoint,
503
- edgeModel.updateEndPoint.bind(edgeModel),
504
- )
505
-
506
- // 而文本需要先算一下文本与默认文本位置之间的相对位置差
507
- // 再计算新路径的文本默认位置,加上相对位置差,得到调整后边的文本的位置
508
- if (text) {
509
- const { x, y } = text
510
- const { x: defaultX, y: defaultY } = textPosition
511
- if (x && y && defaultX && defaultY) {
512
- const deltaX = x - defaultX
513
- const deltaY = y - defaultY
514
- edgeModel.resetTextPosition()
515
- edgeModel.moveText(deltaX, deltaY)
516
- }
517
- }
518
493
  this.edgeModelMap.set(edgeModel.id, edgeModel)
519
494
  this.elementsModelMap.set(edgeModel.id, edgeModel)
520
495
 
@@ -873,6 +848,7 @@ export class GraphModel {
873
848
  */
874
849
  getModelAfterSnapToGrid(node: NodeConfig) {
875
850
  const Model = this.getModel(node.type) as BaseNodeModelCtor
851
+ const { snapGrid } = this.editConfigModel
876
852
  if (!Model) {
877
853
  throw new Error(
878
854
  `找不到${node.type}对应的节点,请确认是否已注册此类型节点。`,
@@ -881,8 +857,8 @@ export class GraphModel {
881
857
  const { x: nodeX, y: nodeY } = node
882
858
  // 根据 grid 修正节点的 x, y
883
859
  if (nodeX && nodeY) {
884
- node.x = snapToGrid(nodeX, this.gridSize)
885
- node.y = snapToGrid(nodeY, this.gridSize)
860
+ node.x = snapToGrid(nodeX, this.gridSize, snapGrid)
861
+ node.y = snapToGrid(nodeY, this.gridSize, snapGrid)
886
862
  if (typeof node.text === 'object' && node.text !== null) {
887
863
  // 原来的处理是:node.text.x -= getGridOffset(nodeX, this.gridSize)
888
864
  // 由于snapToGrid()使用了Math.round()四舍五入的做法,因此无法判断需要执行
@@ -1499,7 +1475,14 @@ export class GraphModel {
1499
1475
  }
1500
1476
 
1501
1477
  /**
1502
- * 更新网格配置
1478
+ * 更新网格尺寸
1479
+ */
1480
+ updateGridSize(size: number) {
1481
+ this.gridSize = size
1482
+ }
1483
+
1484
+ /**
1485
+ * 更新背景配置
1503
1486
  */
1504
1487
  updateBackgroundOptions(
1505
1488
  options: boolean | Partial<LFOptions.BackgroundConfig>,
@@ -1518,8 +1501,11 @@ export class GraphModel {
1518
1501
  * 重新设置画布的宽高
1519
1502
  */
1520
1503
  @action resize(width?: number, height?: number): void {
1521
- this.width = width || this.rootEl.getBoundingClientRect().width
1522
- this.height = height || this.rootEl.getBoundingClientRect().height
1504
+ this.width = width ?? this.rootEl.getBoundingClientRect().width
1505
+ this.isContainerWidth = isNil(width)
1506
+ this.height = height ?? this.rootEl.getBoundingClientRect().height
1507
+ this.isContainerHeight = isNil(height)
1508
+
1523
1509
  if (!this.width || !this.height) {
1524
1510
  console.warn(
1525
1511
  '渲染画布的时候无法获取画布宽高,请确认在container已挂载到DOM。@see https://github.com/didi/LogicFlow/issues/675',
@@ -1533,6 +1519,11 @@ export class GraphModel {
1533
1519
  @action clearData(): void {
1534
1520
  this.nodes = []
1535
1521
  this.edges = []
1522
+
1523
+ // 清除对已清除节点的引用
1524
+ this.edgeModelMap.clear()
1525
+ this.nodeModelMap.clear()
1526
+ this.elementsModelMap.clear()
1536
1527
  }
1537
1528
 
1538
1529
  /**
@@ -1680,6 +1671,7 @@ export class GraphModel {
1680
1671
  console.warn('error on destroy GraphModel', err)
1681
1672
  }
1682
1673
  this.waitCleanEffects.length = 0
1674
+ this.eventCenter.destroy()
1683
1675
  }
1684
1676
  }
1685
1677
 
@@ -392,6 +392,8 @@ export class BaseEdgeModel<P extends PropertiesType = PropertiesType>
392
392
  properties,
393
393
  sourceNodeId: this.sourceNodeId,
394
394
  targetNodeId: this.targetNodeId,
395
+ sourceAnchorId: this.sourceAnchorId,
396
+ targetAnchorId: this.targetAnchorId,
395
397
  startPoint: assign({}, this.startPoint),
396
398
  endPoint: assign({}, this.endPoint),
397
399
  }
@@ -515,14 +517,17 @@ export class BaseEdgeModel<P extends PropertiesType = PropertiesType>
515
517
  * 内部方法,处理初始化文本格式
516
518
  */
517
519
  @action formatText(data: EdgeConfig) {
520
+ const {
521
+ editConfigModel: { edgeTextDraggable, edgeTextEdit },
522
+ } = this.graphModel
518
523
  const { x, y } = this.textPosition
519
524
  const { text } = data
520
525
  let textConfig: Required<TextConfig> = {
521
526
  value: '',
522
527
  x,
523
528
  y,
524
- draggable: false,
525
- editable: true,
529
+ draggable: edgeTextDraggable,
530
+ editable: edgeTextEdit,
526
531
  }
527
532
 
528
533
  if (text) {
@@ -35,6 +35,9 @@ export class PolylineEdgeModel extends BaseEdgeModel {
35
35
 
36
36
  initEdgeData(data: LogicFlow.EdgeConfig): void {
37
37
  this.offset = 30
38
+ if (data.pointsList) {
39
+ this.pointsList = data.pointsList
40
+ }
38
41
  super.initEdgeData(data)
39
42
  }
40
43
 
@@ -315,6 +318,11 @@ export class PolylineEdgeModel extends BaseEdgeModel {
315
318
  return list
316
319
  }
317
320
 
321
+ updatePath(pointList: Point[]) {
322
+ this.pointsList = pointList
323
+ this.points = this.getPath(this.pointsList)
324
+ }
325
+
318
326
  getData() {
319
327
  const data = super.getData()
320
328
  const pointsList = this.pointsList.map(({ x, y }) => ({
@@ -246,13 +246,16 @@ export class BaseNodeModel<P extends PropertiesType = PropertiesType>
246
246
  * 始化文本属性
247
247
  */
248
248
  private formatText(data: NodeConfig): void {
249
+ const {
250
+ editConfigModel: { nodeTextDraggable, nodeTextEdit },
251
+ } = this.graphModel
249
252
  const { x, y, text } = data
250
253
  let textConfig: TextConfig = {
251
254
  value: '',
252
255
  x,
253
256
  y,
254
- draggable: false,
255
- editable: true,
257
+ draggable: nodeTextDraggable,
258
+ editable: nodeTextEdit,
256
259
  }
257
260
  if (text) {
258
261
  if (typeof text === 'string') {
package/src/tool/index.ts CHANGED
@@ -91,6 +91,11 @@ export class Tool {
91
91
  getInstance() {
92
92
  return this.instance
93
93
  }
94
+
95
+ destroy() {
96
+ this.toolMap.clear()
97
+ this.disabledToolMap.clear()
98
+ }
94
99
  }
95
100
 
96
101
  export default Tool
@@ -1,7 +1,9 @@
1
1
  import LogicFlow from '../LogicFlow'
2
2
  import PointTuple = LogicFlow.PointTuple
3
3
 
4
- export function snapToGrid(point: number, gridSize: number) {
4
+ export function snapToGrid(point: number, gridSize: number, snapGrid: boolean) {
5
+ // 开启节网格对齐时才根据网格尺寸校准坐标
6
+ if (!snapGrid) return point
5
7
  // 保证 x, y 的值为 gridSize 的整数倍
6
8
  return gridSize * Math.round(point / gridSize) || point
7
9
  }
@@ -39,9 +39,26 @@ type ContainerStyle = {
39
39
  @observer
40
40
  class Graph extends Component<IGraphProps> {
41
41
  private handleResize = () => {
42
- this.props.graphModel.resize()
42
+ const { graphModel, options } = this.props
43
+ const { width, height, isContainerWidth, isContainerHeight } = graphModel
44
+ let resizeWidth: number | undefined = width
45
+ let resizeHeight: number | undefined = height
46
+ let needUpdate = false
47
+ if (isContainerWidth) {
48
+ resizeWidth = undefined
49
+ needUpdate = true
50
+ }
51
+ if (isContainerHeight) {
52
+ resizeHeight = undefined
53
+ needUpdate = true
54
+ }
55
+ if (needUpdate) {
56
+ graphModel.resize(resizeWidth, resizeHeight)
57
+ }
58
+ options.width = width
59
+ options.height = height
43
60
  }
44
- private throttleResize = () => throttle(this.handleResize, 200)
61
+ private throttleResize = throttle(this.handleResize, 200)
45
62
 
46
63
  componentDidMount() {
47
64
  window.addEventListener('resize', this.throttleResize)
@@ -26,10 +26,13 @@ export class Dnd {
26
26
  })
27
27
  // 处理缩放和偏移
28
28
  const { x: x1, y: y1 } = position.canvasOverlayPosition
29
+ const {
30
+ editConfigModel: { snapGrid },
31
+ } = this.lf.graphModel
29
32
  // x, y 对齐到网格的 size
30
33
  return {
31
- x: snapToGrid(x1, gridSize),
32
- y: snapToGrid(y1, gridSize),
34
+ x: snapToGrid(x1, gridSize, snapGrid),
35
+ y: snapToGrid(y1, gridSize, snapGrid),
33
36
  }
34
37
  }
35
38
 
@@ -358,6 +358,7 @@ export abstract class BaseEdge<P extends IProps> extends Component<
358
358
  clearTimeout(this.clickTimer)
359
359
  }
360
360
  const { model, graphModel } = this.props
361
+ const { editConfigModel } = graphModel
361
362
  const position = graphModel.getPointByClient({
362
363
  x: ev.clientX,
363
364
  y: ev.clientY,
@@ -367,7 +368,10 @@ export abstract class BaseEdge<P extends IProps> extends Component<
367
368
  ElementState.SHOW_MENU,
368
369
  position.domOverlayPosition,
369
370
  )
370
- this.toFront()
371
+ // 静默模式下点击节点不变更节点层级
372
+ if (!editConfigModel.isSilentMode) {
373
+ this.toFront()
374
+ }
371
375
  if (!model.isSelected) {
372
376
  graphModel.selectEdgeById(model.id)
373
377
  }
@@ -456,7 +460,10 @@ export abstract class BaseEdge<P extends IProps> extends Component<
456
460
  }
457
461
  const { editConfigModel } = graphModel
458
462
  graphModel.selectEdgeById(model.id, isMultipleSelect(e, editConfigModel))
459
- this.toFront()
463
+ // 静默模式下点击节点不变更节点层级
464
+ if (!editConfigModel.isSilentMode) {
465
+ this.toFront()
466
+ }
460
467
  }
461
468
 
462
469
  handleFocus = () => {