666ghj commited on
Commit
6a072c9
·
1 Parent(s): e60901f

fix(GraphPanel): optimize force graph drag behavior to prevent simulation restart on click

Browse files

Background:
- With many nodes, D3 force simulation tick callback updates all nodes/edges/labels every frame
- Original implementation called simulation.restart() in drag start event on mousedown
- Even after simulation converged, clicking a node to view details would restart simulation, causing lag

Solution:
- Distinguish between "click" and "drag" using 3px movement threshold
- On drag start: only record initial position, do not restart simulation
- On drag event: detect movement exceeding threshold before marking as actual drag and restarting simulation
- Pure click operations no longer trigger simulation restart, keeping graph static

Bug fix:
- Fixed issue where nodes became undraggable after initial optimization
- Cause: incorrectly used if(!event.active) check in drag event
- event.active equals 1 during drag event, causing restart() to never execute
- Removed that condition, using custom _isDragging flag to control logic instead

frontend/src/components/GraphPanel.vue CHANGED
@@ -661,18 +661,38 @@ const renderGraph = () => {
661
  .style('cursor', 'pointer')
662
  .call(d3.drag()
663
  .on('start', (event, d) => {
664
- if (!event.active) simulation.alphaTarget(0.3).restart()
665
  d.fx = d.x
666
  d.fy = d.y
 
 
 
667
  })
668
  .on('drag', (event, d) => {
669
- d.fx = event.x
670
- d.fy = event.y
 
 
 
 
 
 
 
 
 
 
 
 
 
671
  })
672
  .on('end', (event, d) => {
673
- if (!event.active) simulation.alphaTarget(0)
 
 
 
674
  d.fx = null
675
  d.fy = null
 
676
  })
677
  )
678
  .on('click', (event, d) => {
 
661
  .style('cursor', 'pointer')
662
  .call(d3.drag()
663
  .on('start', (event, d) => {
664
+ // 只记录位置,不重启仿真(区分点击和拖拽)
665
  d.fx = d.x
666
  d.fy = d.y
667
+ d._dragStartX = event.x
668
+ d._dragStartY = event.y
669
+ d._isDragging = false
670
  })
671
  .on('drag', (event, d) => {
672
+ // 检测是否真正开始拖拽(移动超过阈值)
673
+ const dx = event.x - d._dragStartX
674
+ const dy = event.y - d._dragStartY
675
+ const distance = Math.sqrt(dx * dx + dy * dy)
676
+
677
+ if (!d._isDragging && distance > 3) {
678
+ // 首次检测到真正拖拽,才重启仿真
679
+ d._isDragging = true
680
+ simulation.alphaTarget(0.3).restart()
681
+ }
682
+
683
+ if (d._isDragging) {
684
+ d.fx = event.x
685
+ d.fy = event.y
686
+ }
687
  })
688
  .on('end', (event, d) => {
689
+ // 只有真正拖拽过才让仿真逐渐停止
690
+ if (d._isDragging) {
691
+ simulation.alphaTarget(0)
692
+ }
693
  d.fx = null
694
  d.fy = null
695
+ d._isDragging = false
696
  })
697
  )
698
  .on('click', (event, d) => {