@logicflow/core 2.0.9 → 2.0.11

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 (85) hide show
  1. package/.turbo/turbo-build$colon$dev.log +2 -2
  2. package/.turbo/turbo-build.log +7 -7
  3. package/CHANGELOG.md +26 -0
  4. package/dist/index.min.js +1 -1
  5. package/dist/index.min.js.map +1 -1
  6. package/es/LogicFlow.js +21 -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/BezierEdgeModel.js +2 -2
  19. package/es/model/edge/PolylineEdgeModel.d.ts +1 -0
  20. package/es/model/edge/PolylineEdgeModel.js +9 -2
  21. package/es/model/node/BaseNodeModel.js +7 -2
  22. package/es/tool/index.d.ts +1 -0
  23. package/es/tool/index.js +6 -2
  24. package/es/util/geometry.d.ts +1 -1
  25. package/es/util/geometry.js +4 -1
  26. package/es/util/node.d.ts +1 -1
  27. package/es/util/node.js +32 -16
  28. package/es/view/Graph.js +19 -2
  29. package/es/view/behavior/dnd.js +3 -2
  30. package/es/view/edge/BaseEdge.js +9 -2
  31. package/es/view/node/BaseNode.js +20 -11
  32. package/es/view/node/HtmlNode.js +1 -0
  33. package/es/view/overlay/CanvasOverlay.js +6 -4
  34. package/es/view/text/BaseText.js +1 -0
  35. package/lib/LogicFlow.js +20 -0
  36. package/lib/event/eventEmitter.d.ts +1 -0
  37. package/lib/event/eventEmitter.js +3 -0
  38. package/lib/history/index.d.ts +1 -0
  39. package/lib/history/index.js +6 -0
  40. package/lib/keyboard/index.d.ts +1 -0
  41. package/lib/keyboard/index.js +3 -0
  42. package/lib/model/EditConfigModel.d.ts +3 -1
  43. package/lib/model/EditConfigModel.js +5 -0
  44. package/lib/model/GraphModel.d.ts +13 -1
  45. package/lib/model/GraphModel.js +40 -40
  46. package/lib/model/edge/BaseEdgeModel.js +6 -3
  47. package/lib/model/edge/BezierEdgeModel.js +1 -1
  48. package/lib/model/edge/PolylineEdgeModel.d.ts +1 -0
  49. package/lib/model/edge/PolylineEdgeModel.js +8 -1
  50. package/lib/model/node/BaseNodeModel.js +7 -2
  51. package/lib/tool/index.d.ts +1 -0
  52. package/lib/tool/index.js +6 -2
  53. package/lib/util/geometry.d.ts +1 -1
  54. package/lib/util/geometry.js +4 -1
  55. package/lib/util/node.d.ts +1 -1
  56. package/lib/util/node.js +32 -16
  57. package/lib/view/Graph.js +19 -2
  58. package/lib/view/behavior/dnd.js +3 -2
  59. package/lib/view/edge/BaseEdge.js +9 -2
  60. package/lib/view/node/BaseNode.js +19 -10
  61. package/lib/view/node/HtmlNode.js +1 -0
  62. package/lib/view/overlay/CanvasOverlay.js +6 -4
  63. package/lib/view/text/BaseText.js +1 -0
  64. package/package.json +1 -1
  65. package/src/LogicFlow.tsx +25 -1
  66. package/src/event/eventEmitter.ts +4 -0
  67. package/src/history/index.ts +7 -0
  68. package/src/keyboard/index.ts +4 -0
  69. package/src/model/EditConfigModel.ts +4 -0
  70. package/src/model/GraphModel.ts +62 -70
  71. package/src/model/edge/BaseEdgeModel.ts +7 -2
  72. package/src/model/edge/BezierEdgeModel.ts +2 -2
  73. package/src/model/edge/PolylineEdgeModel.ts +10 -2
  74. package/src/model/node/BaseNodeModel.ts +9 -2
  75. package/src/tool/index.ts +7 -2
  76. package/src/util/geometry.ts +3 -1
  77. package/src/util/node.ts +19 -18
  78. package/src/view/Graph.tsx +19 -2
  79. package/src/view/behavior/dnd.ts +5 -2
  80. package/src/view/edge/BaseEdge.tsx +9 -2
  81. package/src/view/node/BaseNode.tsx +20 -12
  82. package/src/view/node/HtmlNode.tsx +1 -0
  83. package/src/view/overlay/CanvasOverlay.tsx +6 -5
  84. package/src/view/text/BaseText.tsx +1 -0
  85. package/stats.html +1 -1
@@ -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) {
@@ -1,4 +1,4 @@
1
- import { assign, cloneDeep } from 'lodash-es'
1
+ import { get, assign, cloneDeep } from 'lodash-es'
2
2
  import { action, observable } from 'mobx'
3
3
  import BaseEdgeModel from './BaseEdgeModel'
4
4
  import { BaseNodeModel } from '../node'
@@ -21,7 +21,7 @@ export class BezierEdgeModel extends BaseEdgeModel {
21
21
  this.setAttributes()
22
22
  }
23
23
  initEdgeData(data: EdgeConfig): void {
24
- this.offset = 100
24
+ this.offset = get(data, 'properties.offset', 100)
25
25
  super.initEdgeData(data)
26
26
  }
27
27
  getEdgeStyle() {
@@ -1,4 +1,4 @@
1
- import { assign, cloneDeep } from 'lodash-es'
1
+ import { get, assign, cloneDeep } from 'lodash-es'
2
2
  import { observable, action } from 'mobx'
3
3
  import { BaseEdgeModel } from '.'
4
4
  import { BaseNodeModel, RectNodeModel, CircleNodeModel, Model } from '..'
@@ -34,7 +34,10 @@ export class PolylineEdgeModel extends BaseEdgeModel {
34
34
  @observable dbClickPosition?: Point
35
35
 
36
36
  initEdgeData(data: LogicFlow.EdgeConfig): void {
37
- this.offset = 30
37
+ this.offset = get(data, 'properties.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') {
@@ -737,6 +740,10 @@ export class BaseNodeModel<P extends PropertiesType = PropertiesType>
737
740
  this.text && this.moveText(0, deltaY)
738
741
  moveY = deltaY
739
742
  }
743
+ this.transform = new TranslateMatrix(-this.x, -this.y)
744
+ .rotate(this.rotate)
745
+ .translate(this.x, this.y)
746
+ .toString()
740
747
  return [moveX, moveY]
741
748
  }
742
749
 
package/src/tool/index.ts CHANGED
@@ -70,7 +70,7 @@ export class Tool {
70
70
  this.toolMap.delete(name)
71
71
  return true
72
72
  }
73
- throw new Error('禁用失败,不存在名为 ${tool} 的工具')
73
+ throw new Error(`禁用失败,不存在名为 ${tool} 的工具`)
74
74
  }
75
75
 
76
76
  @action
@@ -81,7 +81,7 @@ export class Tool {
81
81
  this.disabledToolMap.delete(name)
82
82
  return true
83
83
  }
84
- throw new Error('不存在名为 ${tool} 的工具')
84
+ throw new Error(`不存在名为 ${tool} 的工具`)
85
85
  }
86
86
 
87
87
  getTools() {
@@ -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
  }
package/src/util/node.ts CHANGED
@@ -13,6 +13,7 @@ import {
13
13
  } from '../model'
14
14
  import { SegmentDirection } from '../constant'
15
15
  import { isInSegment } from '../algorithm/edge'
16
+ import { Matrix } from './matrix'
16
17
 
17
18
  import Point = LogicFlow.Point
18
19
  import Direction = LogicFlow.Direction
@@ -112,33 +113,33 @@ export const distance = (
112
113
  ): number => Math.hypot(x1 - x2, y1 - y2)
113
114
 
114
115
  /* 是否在某个节点内,手否进行连接,有offset控制粒度,与outline有关,可以优化 */
115
- export const isInNode = (position: Point, node: BaseNodeModel): boolean => {
116
+ export const isInNode = (
117
+ position: Point,
118
+ node: BaseNodeModel,
119
+ offset = 0,
120
+ ): boolean => {
116
121
  let inNode = false
117
- const offset = 0
118
122
  const bBox = getNodeBBox(node)
123
+ const [x, y] = new Matrix([position.x, position.y, 1])
124
+ .translate(-node.x, -node.y)
125
+ .rotate(-node.rotate)
126
+ .translate(node.x, node.y)[0]
127
+ const reverseRotatedPosition = {
128
+ x,
129
+ y,
130
+ }
119
131
  if (
120
- position.x >= bBox.minX - offset &&
121
- position.x <= bBox.maxX + offset &&
122
- position.y >= bBox.minY - offset &&
123
- position.y <= bBox.maxY + offset
132
+ reverseRotatedPosition.x >= bBox.minX - offset &&
133
+ reverseRotatedPosition.x <= bBox.maxX + offset &&
134
+ reverseRotatedPosition.y >= bBox.minY - offset &&
135
+ reverseRotatedPosition.y <= bBox.maxY + offset
124
136
  ) {
125
137
  inNode = true
126
138
  }
127
139
  return inNode
128
140
  }
129
141
  export const isInNodeBbox = (position: Point, node: BaseNodeModel): boolean => {
130
- let inNode = false
131
- const offset = 5
132
- const bBox = getNodeBBox(node)
133
- if (
134
- position.x >= bBox.minX - offset &&
135
- position.x <= bBox.maxX + offset &&
136
- position.y >= bBox.minY - offset &&
137
- position.y <= bBox.maxY + offset
138
- ) {
139
- inNode = true
140
- }
141
- return inNode
142
+ return isInNode(position, node, 5)
142
143
  }
143
144
 
144
145
  export type NodeBBox = {
@@ -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 = () => {
@@ -13,7 +13,6 @@ import {
13
13
  isMultipleSelect,
14
14
  cancelRaf,
15
15
  createRaf,
16
- TranslateMatrix,
17
16
  IDragParams,
18
17
  // RotateMatrix,
19
18
  } from '../../util'
@@ -80,6 +79,13 @@ export abstract class BaseNode<P extends IProps = IProps> extends Component<
80
79
  if (this.modelDisposer) {
81
80
  this.modelDisposer()
82
81
  }
82
+
83
+ // 以下是 mobx-preact 中 componentWillUnmount 的回调逻辑,但是不知道出于什么考虑,mobx-preact 没有混入这一段逻辑
84
+ // @ts-ignore
85
+ if (this.render.$mobx) {
86
+ // @ts-ignore
87
+ this.render.$mobx.dispose()
88
+ }
83
89
  }
84
90
 
85
91
  componentDidMount() {}
@@ -234,7 +240,7 @@ export abstract class BaseNode<P extends IProps = IProps> extends Component<
234
240
  onDragging = ({ event }: IDragParams) => {
235
241
  const { model, graphModel } = this.props
236
242
  const {
237
- editConfigModel: { stopMoveGraph, autoExpand },
243
+ editConfigModel: { stopMoveGraph, autoExpand, snapGrid },
238
244
  transformModel,
239
245
  selectNodes,
240
246
  width,
@@ -254,9 +260,9 @@ export abstract class BaseNode<P extends IProps = IProps> extends Component<
254
260
  // 2. 考虑鼠标位置不再节点中心
255
261
  x = x + (this.moveOffset?.dx ?? 0)
256
262
  y = y + (this.moveOffset?.dy ?? 0)
257
- // 将x, y移动到grid上
258
- x = snapToGrid(x, gridSize)
259
- y = snapToGrid(y, gridSize)
263
+ // 校准坐标
264
+ x = snapToGrid(x, gridSize, snapGrid)
265
+ y = snapToGrid(y, gridSize, snapGrid)
260
266
  if (!width || !height) {
261
267
  graphModel.moveNode2Coordinate(model.id, x, y)
262
268
  return
@@ -290,11 +296,6 @@ export abstract class BaseNode<P extends IProps = IProps> extends Component<
290
296
  cancelRaf(this.t)
291
297
  }
292
298
 
293
- model.transform = new TranslateMatrix(-x, -y)
294
- .rotate(model.rotate)
295
- .translate(x, y)
296
- .toString()
297
-
298
299
  let moveNodes = selectNodes.map((node) => node.id)
299
300
  // 未被选中的节点也可以拖动
300
301
  if (moveNodes.indexOf(model.id) === -1) {
@@ -371,7 +372,10 @@ export abstract class BaseNode<P extends IProps = IProps> extends Component<
371
372
  } else {
372
373
  graphModel.selectNodeById(model.id, isMultiple)
373
374
  eventOptions.isSelected = true
374
- this.toFront()
375
+ // 静默模式下点击节点不变更节点层级
376
+ if (!editConfigModel.isSilentMode) {
377
+ this.toFront()
378
+ }
375
379
  }
376
380
 
377
381
  // 不是双击的,默认都是单击
@@ -392,6 +396,7 @@ export abstract class BaseNode<P extends IProps = IProps> extends Component<
392
396
  handleContextMenu = (ev: MouseEvent) => {
393
397
  ev.preventDefault()
394
398
  const { model, graphModel } = this.props
399
+ const { editConfigModel } = graphModel
395
400
  // 节点数据,多为事件对象数据抛出
396
401
  const nodeData = model.getData()
397
402
 
@@ -412,7 +417,10 @@ export abstract class BaseNode<P extends IProps = IProps> extends Component<
412
417
  e: ev,
413
418
  position,
414
419
  })
415
- this.toFront()
420
+ // 静默模式下点击节点不变更节点层级
421
+ if (!editConfigModel.isSilentMode) {
422
+ this.toFront()
423
+ }
416
424
  }
417
425
 
418
426
  handleMouseDown = (ev: MouseEvent) => {
@@ -70,6 +70,7 @@ export class HtmlNode<
70
70
  }
71
71
 
72
72
  componentWillUnmount() {
73
+ super.componentWillUnmount()
73
74
  this.rootEl.innerHTML = ''
74
75
  }
75
76
 
@@ -65,8 +65,9 @@ export class CanvasOverlay extends Component<IProps, IState> {
65
65
  graphModel,
66
66
  } = this.props
67
67
  const { deltaX: eX, deltaY: eY } = ev
68
+ const { stopScrollGraph, stopZoomGraph } = editConfigModel
68
69
  // 如果没有禁止滚动移动画布, 并且当前触发的时候ctrl键、cmd键没有按住, 那么移动画布
69
- if (!editConfigModel.stopScrollGraph && !ev.ctrlKey && !ev.metaKey) {
70
+ if (!stopScrollGraph && !ev.ctrlKey && !ev.metaKey) {
70
71
  ev.preventDefault()
71
72
  this.stepScrollX += eX
72
73
  this.stepScrollY += eY
@@ -85,7 +86,7 @@ export class CanvasOverlay extends Component<IProps, IState> {
85
86
  return
86
87
  }
87
88
  // 如果没有禁止缩放画布,那么进行缩放. 在禁止缩放画布后,按住 ctrl、cmd 键也不能缩放了。
88
- if (!editConfigModel.stopZoomGraph) {
89
+ if (!stopZoomGraph) {
89
90
  ev.preventDefault()
90
91
  const position = graphModel.getPointByClient({
91
92
  x: ev.clientX,
@@ -133,11 +134,11 @@ export class CanvasOverlay extends Component<IProps, IState> {
133
134
  gridSize,
134
135
  },
135
136
  } = this.props
137
+ const { adjustEdge, adjustNodePosition, stopMoveGraph } = editConfigModel
136
138
  const target = ev.target as HTMLElement
137
- const isFrozenElement =
138
- !editConfigModel.adjustEdge && !editConfigModel.adjustNodePosition
139
+ const isFrozenElement = !adjustEdge && !adjustNodePosition
139
140
  if (target.getAttribute('name') === 'canvas-overlay' || isFrozenElement) {
140
- if (editConfigModel.stopMoveGraph !== true) {
141
+ if (stopMoveGraph !== true) {
141
142
  this.stepDrag.setStep(gridSize * SCALE_X)
142
143
  this.stepDrag.handleMouseDown(ev)
143
144
  } else {
@@ -80,6 +80,7 @@ export class BaseText<
80
80
  } = graphModel
81
81
 
82
82
  if (draggable ?? nodeTextDraggable) {
83
+ e.stopPropagation()
83
84
  this.stepperDrag.model = model
84
85
  this.stepperDrag.handleMouseDown(e)
85
86
  }