@logicflow/core 2.1.4 → 2.2.0-alpha.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 (82) hide show
  1. package/.turbo/turbo-build$colon$dev.log +57 -2
  2. package/.turbo/turbo-build.log +7 -7
  3. package/CHANGELOG.md +15 -0
  4. package/dist/index.min.js +1 -1
  5. package/dist/index.min.js.map +1 -1
  6. package/es/model/EditConfigModel.d.ts +5 -1
  7. package/es/model/EditConfigModel.js +10 -0
  8. package/es/model/GraphModel.d.ts +1 -0
  9. package/es/model/GraphModel.js +3 -1
  10. package/es/model/node/BaseNodeModel.js +3 -1
  11. package/es/options.d.ts +3 -1
  12. package/es/tool/MultipleSelectTool.d.ts +1 -1
  13. package/es/tool/MultipleSelectTool.js +1 -1
  14. package/es/util/drag.d.ts +4 -4
  15. package/es/util/drag.js +11 -6
  16. package/es/view/Anchor.d.ts +4 -3
  17. package/es/view/Anchor.js +58 -23
  18. package/es/view/Control.js +1 -1
  19. package/es/view/Rotate.js +1 -1
  20. package/es/view/behavior/dnd.d.ts +4 -8
  21. package/es/view/behavior/dnd.js +50 -14
  22. package/es/view/edge/AdjustPoint.d.ts +1 -1
  23. package/es/view/edge/AdjustPoint.js +1 -1
  24. package/es/view/edge/BaseEdge.d.ts +2 -1
  25. package/es/view/edge/BaseEdge.js +18 -1
  26. package/es/view/edge/PolylineEdge.d.ts +1 -1
  27. package/es/view/edge/PolylineEdge.js +1 -1
  28. package/es/view/node/BaseNode.d.ts +2 -1
  29. package/es/view/node/BaseNode.js +17 -1
  30. package/es/view/overlay/BezierAdjustOverlay.js +1 -1
  31. package/es/view/overlay/CanvasOverlay.d.ts +12 -1
  32. package/es/view/overlay/CanvasOverlay.js +94 -15
  33. package/es/view/text/BaseText.d.ts +1 -1
  34. package/es/view/text/BaseText.js +1 -1
  35. package/lib/model/EditConfigModel.d.ts +5 -1
  36. package/lib/model/EditConfigModel.js +10 -0
  37. package/lib/model/GraphModel.d.ts +1 -0
  38. package/lib/model/GraphModel.js +3 -1
  39. package/lib/model/node/BaseNodeModel.js +3 -1
  40. package/lib/options.d.ts +3 -1
  41. package/lib/tool/MultipleSelectTool.d.ts +1 -1
  42. package/lib/tool/MultipleSelectTool.js +1 -1
  43. package/lib/util/drag.d.ts +4 -4
  44. package/lib/util/drag.js +11 -6
  45. package/lib/view/Anchor.d.ts +4 -3
  46. package/lib/view/Anchor.js +58 -23
  47. package/lib/view/Control.js +1 -1
  48. package/lib/view/Rotate.js +1 -1
  49. package/lib/view/behavior/dnd.d.ts +4 -8
  50. package/lib/view/behavior/dnd.js +50 -14
  51. package/lib/view/edge/AdjustPoint.d.ts +1 -1
  52. package/lib/view/edge/AdjustPoint.js +1 -1
  53. package/lib/view/edge/BaseEdge.d.ts +2 -1
  54. package/lib/view/edge/BaseEdge.js +18 -1
  55. package/lib/view/edge/PolylineEdge.d.ts +1 -1
  56. package/lib/view/edge/PolylineEdge.js +1 -1
  57. package/lib/view/node/BaseNode.d.ts +2 -1
  58. package/lib/view/node/BaseNode.js +17 -1
  59. package/lib/view/overlay/BezierAdjustOverlay.js +1 -1
  60. package/lib/view/overlay/CanvasOverlay.d.ts +12 -1
  61. package/lib/view/overlay/CanvasOverlay.js +94 -15
  62. package/lib/view/text/BaseText.d.ts +1 -1
  63. package/lib/view/text/BaseText.js +1 -1
  64. package/package.json +1 -1
  65. package/src/model/EditConfigModel.ts +6 -0
  66. package/src/model/GraphModel.ts +5 -0
  67. package/src/model/node/BaseNodeModel.ts +4 -1
  68. package/src/options.ts +6 -1
  69. package/src/tool/MultipleSelectTool.tsx +2 -2
  70. package/src/util/drag.ts +15 -12
  71. package/src/view/Anchor.tsx +84 -35
  72. package/src/view/Control.tsx +1 -1
  73. package/src/view/Rotate.tsx +1 -1
  74. package/src/view/behavior/dnd.ts +55 -16
  75. package/src/view/edge/AdjustPoint.tsx +2 -2
  76. package/src/view/edge/BaseEdge.tsx +23 -3
  77. package/src/view/edge/PolylineEdge.tsx +2 -2
  78. package/src/view/node/BaseNode.tsx +21 -5
  79. package/src/view/overlay/BezierAdjustOverlay.tsx +1 -1
  80. package/src/view/overlay/CanvasOverlay.tsx +110 -4
  81. package/src/view/text/BaseText.tsx +5 -2
  82. package/stats.html +1 -1
package/src/util/drag.ts CHANGED
@@ -10,7 +10,7 @@ const LEFT_MOUSE_BUTTON_CODE = 0
10
10
  export type IDragParams = {
11
11
  deltaX: number
12
12
  deltaY: number
13
- event?: MouseEvent
13
+ event?: PointerEvent
14
14
  [key: string]: unknown
15
15
  }
16
16
 
@@ -99,16 +99,15 @@ export class StepDrag {
99
99
  this.model = model
100
100
  }
101
101
 
102
- handleMouseDown = (e: MouseEvent) => {
102
+ handleMouseDown = (e: PointerEvent) => {
103
103
  const DOC: any = window?.document
104
104
  if (e.button !== LEFT_MOUSE_BUTTON_CODE) return
105
105
  if (this.isStopPropagation) e.stopPropagation()
106
106
  this.isStartDragging = true
107
107
  this.startX = e.clientX
108
108
  this.startY = e.clientY
109
-
110
- DOC.addEventListener('mousemove', this.handleMouseMove, false)
111
- DOC.addEventListener('mouseup', this.handleMouseUp, false)
109
+ DOC.addEventListener('pointermove', this.handleMouseMove, false)
110
+ DOC.addEventListener('pointerup', this.handleMouseUp, false)
112
111
  const elementData = this.model?.getData()
113
112
  this.eventCenter?.emit(EventType[`${this.eventType}_MOUSEDOWN`], {
114
113
  e,
@@ -117,8 +116,9 @@ export class StepDrag {
117
116
  this.startTime = new Date().getTime()
118
117
  }
119
118
 
120
- handleMouseMove = (e: MouseEvent) => {
119
+ handleMouseMove = (e: PointerEvent) => {
121
120
  if (this.isStopPropagation) e.stopPropagation()
121
+ e.preventDefault()
122
122
  if (!this.isStartDragging) return
123
123
  this.sumDeltaX += e.clientX - this.startX
124
124
  this.sumDeltaY += e.clientY - this.startY
@@ -170,15 +170,19 @@ export class StepDrag {
170
170
  }
171
171
  }
172
172
 
173
- handleMouseUp = (e: MouseEvent) => {
173
+ handleMouseUp = (e: PointerEvent) => {
174
174
  const DOC = window.document
175
175
 
176
176
  this.isStartDragging = false
177
177
  if (this.isStopPropagation) e.stopPropagation()
178
+ const target = e.target as any
179
+ if (target && typeof target.releasePointerCapture === 'function') {
180
+ target.releasePointerCapture(e.pointerId)
181
+ }
178
182
  // fix #568: 如果onDragging在下一个事件循环中触发,而drop在当前事件循环,会出现问题。
179
183
  Promise.resolve().then(() => {
180
- DOC.removeEventListener('mousemove', this.handleMouseMove, false)
181
- DOC.removeEventListener('mouseup', this.handleMouseUp, false)
184
+ DOC.removeEventListener('pointermove', this.handleMouseMove, false)
185
+ DOC.removeEventListener('pointerup', this.handleMouseUp, false)
182
186
  const elementData = this.model?.getData()
183
187
  this.eventCenter?.emit(EventType[`${this.eventType}_MOUSEUP`], {
184
188
  e,
@@ -195,9 +199,8 @@ export class StepDrag {
195
199
  }
196
200
  cancelDrag = () => {
197
201
  const DOC: any = window?.document
198
-
199
- DOC.removeEventListener('mousemove', this.handleMouseMove, false)
200
- DOC.removeEventListener('mouseup', this.handleMouseUp, false)
202
+ DOC.removeEventListener('pointermove', this.handleMouseMove, false)
203
+ DOC.removeEventListener('pointerup', this.handleMouseUp, false)
201
204
  this.onDragEnd({ event: undefined })
202
205
  this.isDragging = false
203
206
  }
@@ -29,7 +29,7 @@ interface IProps {
29
29
  anchorIndex: number
30
30
  graphModel: GraphModel
31
31
  nodeModel: BaseNodeModel
32
- setHoverOff: (e: MouseEvent) => void
32
+ setHoverOff: (e: PointerEvent) => void
33
33
  }
34
34
 
35
35
  interface IState {
@@ -154,7 +154,7 @@ class Anchor extends Component<IProps, IState> {
154
154
  endY: y1,
155
155
  dragging: true,
156
156
  })
157
- this.moveAnchorEnd(x1, y1)
157
+ this.moveAnchorEnd(x1, y1, event)
158
158
  if (nearBoundary.length > 0 && !stopMoveGraph && autoExpand) {
159
159
  this.t = createRaf(() => {
160
160
  const [translateX, translateY] = nearBoundary
@@ -164,7 +164,7 @@ class Anchor extends Component<IProps, IState> {
164
164
  endX: endX - translateX,
165
165
  endY: endY - translateY,
166
166
  })
167
- this.moveAnchorEnd(endX - translateX, endY - translateY)
167
+ this.moveAnchorEnd(endX - translateX, endY - translateY, event)
168
168
  })
169
169
  }
170
170
  eventCenter.emit(EventType.ANCHOR_DRAG, {
@@ -189,6 +189,11 @@ class Anchor extends Component<IProps, IState> {
189
189
  this.sourceRuleResults.clear()
190
190
  this.targetRuleResults.clear()
191
191
  const { graphModel, nodeModel, anchorData } = this.props
192
+ // 拖拽结束清理:取消悬浮态
193
+ if (this.preTargetNode) {
194
+ this.preTargetNode.setHovered(false)
195
+ this.preTargetNode = undefined
196
+ }
192
197
 
193
198
  graphModel.eventCenter.emit(EventType.ANCHOR_DRAGEND, {
194
199
  data: anchorData,
@@ -216,7 +221,7 @@ class Anchor extends Component<IProps, IState> {
216
221
  }
217
222
  }
218
223
 
219
- checkEnd = (event: MouseEvent | null | undefined) => {
224
+ checkEnd = (event: PointerEvent | null | undefined) => {
220
225
  const {
221
226
  graphModel,
222
227
  nodeModel,
@@ -289,7 +294,7 @@ class Anchor extends Component<IProps, IState> {
289
294
  }
290
295
  }
291
296
 
292
- moveAnchorEnd(endX: number, endY: number) {
297
+ moveAnchorEnd(endX: number, endY: number, event?: PointerEvent) {
293
298
  const { graphModel, nodeModel, anchorData } = this.props
294
299
  const info = targetNodeInfo(
295
300
  {
@@ -309,40 +314,31 @@ class Anchor extends Component<IProps, IState> {
309
314
  return
310
315
  }
311
316
  this.preTargetNode = targetNode
312
- // 支持节点的每个锚点单独设置是否可连接,因此规则key去nodeId + anchorId作为唯一值
313
- const targetInfoId = `${nodeModel.id}_${targetNode.id}_${anchorId}_${anchorData.id}`
314
-
315
- // 查看鼠标是否进入过target,若有检验结果,表示进入过, 就不重复计算了。
316
- if (!this.targetRuleResults.has(targetInfoId)) {
317
- const targetAnchor = info.anchor
318
- const sourceRuleResult = nodeModel.isAllowConnectedAsSource(
317
+ const anchorDist = distance(endX, endY, info.anchor.x, info.anchor.y)
318
+ const validateDistance = 10
319
+ const { editConfigModel } = graphModel
320
+ if (
321
+ !editConfigModel.anchorProximityValidate ||
322
+ anchorDist <= validateDistance
323
+ ) {
324
+ this.validateAndSetState(
319
325
  targetNode,
320
- anchorData,
321
- targetAnchor,
322
- )
323
- const targetRuleResult = targetNode.isAllowConnectedAsTarget(
326
+ anchorId,
327
+ info.anchor,
324
328
  nodeModel,
325
329
  anchorData,
326
- targetAnchor,
327
- )
328
- this.sourceRuleResults.set(
329
- targetInfoId,
330
- formatAnchorConnectValidateData(sourceRuleResult),
331
- )
332
- this.targetRuleResults.set(
333
- targetInfoId,
334
- formatAnchorConnectValidateData(targetRuleResult),
335
330
  )
336
331
  }
337
- const { isAllPass: isSourcePass } =
338
- this.sourceRuleResults.get(targetInfoId) ?? {}
339
- const { isAllPass: isTargetPass } =
340
- this.targetRuleResults.get(targetInfoId) ?? {}
341
- // 实时提示出即将链接的锚点
342
- if (isSourcePass && isTargetPass) {
343
- targetNode.setElementState(ElementState.ALLOW_CONNECT)
344
- } else {
345
- targetNode.setElementState(ElementState.NOT_ALLOW_CONNECT)
332
+ // 人工触发进入目标节点事件,同步设置 hovered 以驱动锚点显隐和样式
333
+ if (!targetNode.isHovered) {
334
+ const nodeData = targetNode.getData()
335
+ if (event) {
336
+ graphModel.eventCenter.emit(EventType.NODE_MOUSEENTER, {
337
+ data: nodeData,
338
+ e: event,
339
+ })
340
+ }
341
+ targetNode.setHovered(true)
346
342
  }
347
343
  } else if (
348
344
  this.preTargetNode &&
@@ -350,6 +346,59 @@ class Anchor extends Component<IProps, IState> {
350
346
  ) {
351
347
  // 为了保证鼠标离开的时候,将上一个节点状态重置为正常状态。
352
348
  this.preTargetNode.setElementState(ElementState.DEFAULT)
349
+ // 未命中任何节点:人工派发离开事件并取消悬浮,避免状态残留
350
+ const prevData = this.preTargetNode.getData()
351
+ if (event) {
352
+ graphModel.eventCenter.emit(EventType.NODE_MOUSELEAVE, {
353
+ data: prevData,
354
+ e: event,
355
+ })
356
+ }
357
+ this.preTargetNode.setHovered(false)
358
+ this.preTargetNode = undefined
359
+ }
360
+ }
361
+
362
+ // 校验 source/target 连接规则并设置目标节点状态
363
+ validateAndSetState(
364
+ targetNode: BaseNodeModel,
365
+ anchorId: string | undefined,
366
+ targetAnchor: AnchorConfig,
367
+ nodeModel: BaseNodeModel,
368
+ anchorData: AnchorConfig,
369
+ ) {
370
+ const targetInfoId = `${nodeModel.id}_${targetNode.id}_${anchorId}_${anchorData.id}`
371
+ if (!this.targetRuleResults.has(targetInfoId)) {
372
+ // 首次计算并缓存源/目标两侧的规则校验结果
373
+ const sourceRuleResult = nodeModel.isAllowConnectedAsSource(
374
+ targetNode,
375
+ anchorData,
376
+ targetAnchor,
377
+ )
378
+ const targetRuleResult = targetNode.isAllowConnectedAsTarget(
379
+ nodeModel,
380
+ anchorData,
381
+ targetAnchor,
382
+ )
383
+ this.sourceRuleResults.set(
384
+ targetInfoId,
385
+ formatAnchorConnectValidateData(sourceRuleResult),
386
+ )
387
+ this.targetRuleResults.set(
388
+ targetInfoId,
389
+ formatAnchorConnectValidateData(targetRuleResult),
390
+ )
391
+ }
392
+ // 读取缓存的校验结果
393
+ const { isAllPass: isSourcePass } =
394
+ this.sourceRuleResults.get(targetInfoId) ?? {}
395
+ const { isAllPass: isTargetPass } =
396
+ this.targetRuleResults.get(targetInfoId) ?? {}
397
+ // 两侧都通过则允许连接,否则标记为不允许连接
398
+ if (isSourcePass && isTargetPass) {
399
+ targetNode.setElementState(ElementState.ALLOW_CONNECT)
400
+ } else {
401
+ targetNode.setElementState(ElementState.NOT_ALLOW_CONNECT)
353
402
  }
354
403
  }
355
404
 
@@ -375,7 +424,7 @@ class Anchor extends Component<IProps, IState> {
375
424
  nodeModel,
376
425
  })
377
426
  }}
378
- onMouseDown={(ev) => {
427
+ onPointerDown={(ev) => {
379
428
  graphModel.eventCenter.emit(EventType.ANCHOR_MOUSEDOWN, {
380
429
  data: anchorData,
381
430
  e: ev!,
@@ -393,7 +393,7 @@ export class ResizeControl extends Component<
393
393
  height={25}
394
394
  fill="transparent"
395
395
  stroke="transparent"
396
- onMouseDown={this.dragHandler.handleMouseDown}
396
+ onPointerDown={this.dragHandler.handleMouseDown}
397
397
  />
398
398
  </g>
399
399
  )
@@ -99,7 +99,7 @@ class RotateControlPoint extends Component<IRotateControlProps> {
99
99
  return (
100
100
  <g className="lf-rotate-control">
101
101
  <g
102
- onMouseDown={(ev) => {
102
+ onPointerDown={(ev) => {
103
103
  this.stepperDrag.handleMouseDown(ev)
104
104
  }}
105
105
  >
@@ -11,6 +11,8 @@ export class Dnd {
11
11
  nodeConfig: OnDragNodeConfig | null = null
12
12
  lf: LogicFlow
13
13
  fakeNode: BaseNodeModel | null = null
14
+ docPointerMove?: (e: PointerEvent) => void
15
+ docPointerUp?: (e: PointerEvent) => void
14
16
 
15
17
  constructor(params: { lf: LogicFlow }) {
16
18
  const { lf } = params
@@ -36,19 +38,67 @@ export class Dnd {
36
38
  }
37
39
  }
38
40
 
41
+ isInsideCanvas(e: PointerEvent): boolean {
42
+ const overlay = this.lf.graphModel.rootEl.querySelector(
43
+ '[name="canvas-overlay"]',
44
+ ) as HTMLElement | null
45
+ const topEl = window.document.elementFromPoint(
46
+ e.clientX,
47
+ e.clientY,
48
+ ) as HTMLElement | null
49
+ return (
50
+ topEl === overlay ||
51
+ (topEl !== null && !!overlay && overlay.contains(topEl))
52
+ )
53
+ }
39
54
  startDrag(nodeConfig: OnDragNodeConfig) {
40
55
  const { editConfigModel } = this.lf.graphModel
41
- if (!editConfigModel?.isSilentMode) {
42
- this.nodeConfig = nodeConfig
43
- window.document.addEventListener('mouseup', this.stopDrag)
56
+ if (editConfigModel?.isSilentMode) return
57
+ this.nodeConfig = nodeConfig
58
+ // 指针移动:根据命中结果判断是否在画布覆盖层上,驱动假节点创建/移动或清理
59
+ this.docPointerMove = (e: PointerEvent) => {
60
+ if (!this.nodeConfig) return
61
+ // 离开画布:清理吸附线与假节点
62
+ if (!this.isInsideCanvas(e)) {
63
+ this.onDragLeave()
64
+ return
65
+ }
66
+ // 首次进入画布:创建假节点并初始化位置
67
+ if (!this.fakeNode) {
68
+ this.dragEnter(e)
69
+ return
70
+ }
71
+ // 在画布内移动:更新假节点位置与吸附线
72
+ this.onDragOver(e)
73
+ }
74
+ // 指针抬起:在画布内落点生成节点,否则清理假节点
75
+ this.docPointerUp = (e: PointerEvent) => {
76
+ if (!this.nodeConfig) return
77
+ if (this.isInsideCanvas(e)) {
78
+ this.onDrop(e)
79
+ } else {
80
+ this.onDragLeave()
81
+ }
82
+ // 阻止默认行为与冒泡,避免滚动/点击穿透
83
+ e.preventDefault()
84
+ e.stopPropagation()
85
+ // 结束拖拽并移除监听
86
+ this.stopDrag()
44
87
  }
88
+ window.document.addEventListener('pointermove', this.docPointerMove)
89
+ window.document.addEventListener('pointerup', this.docPointerUp)
45
90
  }
46
91
 
47
92
  stopDrag = () => {
48
93
  this.nodeConfig = null
49
- window.document.removeEventListener('mouseup', this.stopDrag)
94
+ if (this.docPointerMove) {
95
+ window.document.removeEventListener('pointermove', this.docPointerMove)
96
+ }
97
+ if (this.docPointerUp) {
98
+ window.document.removeEventListener('pointerup', this.docPointerUp)
99
+ }
50
100
  }
51
- dragEnter = (e: MouseEvent) => {
101
+ dragEnter = (e: PointerEvent) => {
52
102
  if (!this.nodeConfig || this.fakeNode) return
53
103
  this.fakeNode = this.lf.createFakeNode({
54
104
  ...this.nodeConfig,
@@ -107,17 +157,6 @@ export class Dnd {
107
157
  this.lf.graphModel.removeFakeNode()
108
158
  this.fakeNode = null
109
159
  }
110
-
111
- eventMap() {
112
- return {
113
- onMouseEnter: this.dragEnter,
114
- onMouseOver: this.dragEnter, // IE11
115
- onMouseMove: this.onDragOver,
116
- onMouseLeave: this.onDragLeave,
117
- // onMouseOut: this.onDragLeave, // IE11
118
- onMouseUp: this.onDrop,
119
- }
120
- }
121
160
  }
122
161
 
123
162
  export default Dnd
@@ -78,7 +78,7 @@ export class AdjustPoint extends Component<IProps, IState> {
78
78
  })
79
79
  }
80
80
 
81
- handleMouseDown = (ev: MouseEvent) => {
81
+ handleMouseDown = (ev: PointerEvent) => {
82
82
  if (this.stepDrag) {
83
83
  this.stepDrag.handleMouseDown(ev)
84
84
  }
@@ -414,7 +414,7 @@ export class AdjustPoint extends Component<IProps, IState> {
414
414
  return (
415
415
  <g
416
416
  pointerEvents={dragging ? 'none' : ''}
417
- onMouseDown={this.handleMouseDown}
417
+ onPointerDown={this.handleMouseDown}
418
418
  >
419
419
  {!dragging ? getAdjustPointShape(x, y, edgeModel) : ''}
420
420
  </g>
@@ -34,6 +34,7 @@ export abstract class BaseEdge<P extends IProps> extends Component<
34
34
  startTime?: number
35
35
  contextMenuTime?: number
36
36
  clickTimer?: number
37
+ longPressTimer?: number
37
38
  textRef = createRef()
38
39
 
39
40
  constructor() {
@@ -479,13 +480,27 @@ export abstract class BaseEdge<P extends IProps> extends Component<
479
480
  /**
480
481
  * 不支持重写
481
482
  */
482
- handleMouseDown = (e: MouseEvent) => {
483
+ handleMouseDown = (e: PointerEvent) => {
483
484
  e.stopPropagation()
484
485
  this.startTime = new Date().getTime()
486
+ if (this.longPressTimer) {
487
+ clearTimeout(this.longPressTimer)
488
+ }
489
+ if (e.pointerType === 'touch') {
490
+ this.longPressTimer = window.setTimeout(() => {
491
+ if (!this.props.model.isDragging) {
492
+ this.handleContextMenu(e)
493
+ }
494
+ }, 500)
495
+ }
485
496
  }
486
497
  handleMouseUp = () => {
487
498
  const { model } = this.props
488
499
  this.mouseUpDrag = model.isDragging
500
+ if (this.longPressTimer) {
501
+ clearTimeout(this.longPressTimer)
502
+ this.longPressTimer = undefined
503
+ }
489
504
  }
490
505
  /**
491
506
  * 不支持重写
@@ -606,10 +621,15 @@ export abstract class BaseEdge<P extends IProps> extends Component<
606
621
  ]
607
622
  .filter(Boolean)
608
623
  .join(' ')}
609
- onMouseDown={this.handleMouseDown}
610
- onMouseUp={this.handleMouseUp}
624
+ style={{
625
+ touchAction: 'none',
626
+ WebkitTouchCallout: 'none',
627
+ }}
611
628
  onClick={this.handleClick}
612
629
  onContextMenu={this.handleContextMenu}
630
+ onPointerDown={this.handleMouseDown}
631
+ onPointerUp={this.handleMouseUp}
632
+ onPointerCancel={this.handleMouseUp}
613
633
  onMouseOver={this.setHoverOn}
614
634
  onMouseEnter={this.setHoverOn}
615
635
  onMouseLeave={this.setHoverOff}
@@ -95,7 +95,7 @@ export class PolylineEdge extends BaseEdge<IPolylineEdgeProps> {
95
95
  /**
96
96
  * 不支持重写
97
97
  */
98
- beforeDragStart = (e, appendInfo) => {
98
+ beforeDragStart = (e: PointerEvent, appendInfo) => {
99
99
  // 如果允许拖拽调整触发事件处理
100
100
  if (appendInfo.draggable) {
101
101
  this.drag.handleMouseDown(e)
@@ -284,7 +284,7 @@ export class PolylineEdge extends BaseEdge<IPolylineEdgeProps> {
284
284
  append = (
285
285
  <g
286
286
  className={this.isDragging ? 'lf-dragging' : 'lf-drag-able'}
287
- onMouseDown={(e) => this.beforeDragStart(e, appendInfo)}
287
+ onPointerDown={(e) => this.beforeDragStart(e, appendInfo)}
288
288
  >
289
289
  <g className={className}>{this.getAppendShape(appendInfo)}</g>
290
290
  </g>
@@ -42,6 +42,7 @@ export abstract class BaseNode<P extends IProps = IProps> extends Component<
42
42
  mouseUpDrag?: boolean
43
43
  startTime?: number
44
44
  modelDisposer: IReactionDisposer
45
+ longPressTimer?: number
45
46
 
46
47
  constructor(props: IProps) {
47
48
  super()
@@ -88,9 +89,9 @@ export abstract class BaseNode<P extends IProps = IProps> extends Component<
88
89
  }
89
90
  }
90
91
 
91
- componentDidMount() { }
92
+ componentDidMount() {}
92
93
 
93
- componentDidUpdate() { }
94
+ componentDidUpdate() {}
94
95
 
95
96
  abstract getShape(): h.JSX.Element | null
96
97
 
@@ -330,6 +331,10 @@ export abstract class BaseNode<P extends IProps = IProps> extends Component<
330
331
  handleMouseUp = () => {
331
332
  const { model } = this.props
332
333
  this.mouseUpDrag = model.isDragging
334
+ if (this.longPressTimer) {
335
+ clearTimeout(this.longPressTimer)
336
+ this.longPressTimer = undefined
337
+ }
333
338
  }
334
339
 
335
340
  handleClick = (e: MouseEvent) => {
@@ -431,13 +436,23 @@ export abstract class BaseNode<P extends IProps = IProps> extends Component<
431
436
  }
432
437
  }
433
438
 
434
- handleMouseDown = (ev: MouseEvent) => {
439
+ handleMouseDown = (ev: PointerEvent) => {
435
440
  const { model, graphModel } = this.props
436
441
  this.startTime = new Date().getTime()
437
442
  const { editConfigModel } = graphModel
438
443
  if (editConfigModel.adjustNodePosition && model.draggable) {
439
444
  this.stepDrag && this.stepDrag.handleMouseDown(ev)
440
445
  }
446
+ if (this.longPressTimer) {
447
+ clearTimeout(this.longPressTimer)
448
+ }
449
+ if (ev.pointerType === 'touch') {
450
+ this.longPressTimer = window.setTimeout(() => {
451
+ if (!this.props.model.isDragging) {
452
+ this.handleContextMenu(ev)
453
+ }
454
+ }, 500)
455
+ }
441
456
  }
442
457
 
443
458
  handleFocus = () => {
@@ -532,9 +547,10 @@ export abstract class BaseNode<P extends IProps = IProps> extends Component<
532
547
  nodeShape = (
533
548
  <g
534
549
  className={`${this.getStateClassName()} ${className}`}
535
- onMouseDown={this.handleMouseDown}
536
- onMouseUp={this.handleMouseUp}
550
+ onPointerDown={this.handleMouseDown}
551
+ onPointerUp={this.handleMouseUp}
537
552
  onClick={this.handleClick}
553
+ //因为移动端点击操作完成会按顺序触发enter、leave、click事件,所以会造成节点的闪烁,所以在这里没有统一状态为Pointer
538
554
  onMouseEnter={this.setHoverOn}
539
555
  onMouseOver={this.setHoverOn}
540
556
  onMouseLeave={this.setHoverOff}
@@ -71,7 +71,7 @@ export class BezierAdjustAnchor extends Component<IAnchorProps, IState> {
71
71
  x={x}
72
72
  y={y}
73
73
  {...adjustAnchor}
74
- onMouseDown={(ev) => {
74
+ onPointerDown={(ev) => {
75
75
  // if (edgeAddable !== false) {
76
76
  this.dragHandler.handleMouseDown(ev)
77
77
  // }