1- import React , { useRef , useEffect , useState , useCallback } from 'react' ;
1+ import React , { useRef , useEffect , useState } from 'react' ;
22import * as d3 from 'd3' ;
33import type { VisualNode , AlgorithmStep , Annotation } from '../types' ;
44import './TrieCanvas.css' ;
@@ -24,81 +24,6 @@ const TrieCanvas: React.FC<TrieCanvasProps> = ({ currentStep }) => {
2424 const [ isDragging , setIsDragging ] = useState ( false ) ;
2525 const [ dragStart , setDragStart ] = useState ( { x : 0 , y : 0 } ) ;
2626
27- // 计算树的布局
28- const calculateLayout = useCallback ( ( node : VisualNode | null , depth : number = 0 , index : number = 0 , siblingCount : number = 1 ) : TreeNode | null => {
29- if ( ! node ) return null ;
30-
31- const horizontalSpacing = 70 ;
32- const verticalSpacing = 80 ;
33-
34- // 计算子节点
35- const children : TreeNode [ ] = [ ] ;
36- node . children . forEach ( ( child , i ) => {
37- const childNode = calculateLayout ( child , depth + 1 , i , node . children . length ) ;
38- if ( childNode ) children . push ( childNode ) ;
39- } ) ;
40-
41- // 计算当前节点位置
42- let x = 0 ;
43- if ( children . length > 0 ) {
44- // 父节点居中于子节点
45- const leftMost = children [ 0 ] . x ;
46- const rightMost = children [ children . length - 1 ] . x ;
47- x = ( leftMost + rightMost ) / 2 ;
48- } else {
49- x = ( index - ( siblingCount - 1 ) / 2 ) * horizontalSpacing ;
50- }
51-
52- return {
53- id : node . id ,
54- char : node . char ,
55- isEnd : node . isEnd ,
56- x,
57- y : depth * verticalSpacing ,
58- children,
59- highlighted : currentStep ?. highlightedNodes . includes ( node . id ) || false ,
60- } ;
61- } , [ currentStep ] ) ;
62-
63- // 调整树的位置避免重叠
64- const adjustTreePositions = useCallback ( ( root : TreeNode | null ) : TreeNode | null => {
65- if ( ! root ) return null ;
66-
67- const nodePositions : Map < number , number [ ] > = new Map ( ) ;
68-
69- const collectPositions = ( node : TreeNode ) => {
70- const level = Math . round ( node . y / 80 ) ;
71- if ( ! nodePositions . has ( level ) ) {
72- nodePositions . set ( level , [ ] ) ;
73- }
74- nodePositions . get ( level ) ! . push ( node . x ) ;
75- node . children . forEach ( collectPositions ) ;
76- } ;
77-
78- const adjustNode = ( node : TreeNode , offset : number ) : TreeNode => {
79- return {
80- ...node ,
81- x : node . x + offset ,
82- children : node . children . map ( child => adjustNode ( child , offset ) ) ,
83- } ;
84- } ;
85-
86- collectPositions ( root ) ;
87-
88- // 找到最小x值,确保树居中
89- let minX = Infinity ;
90- let maxX = - Infinity ;
91- nodePositions . forEach ( positions => {
92- positions . forEach ( x => {
93- minX = Math . min ( minX , x ) ;
94- maxX = Math . max ( maxX , x ) ;
95- } ) ;
96- } ) ;
97-
98- const centerOffset = - ( minX + maxX ) / 2 ;
99- return adjustNode ( root , centerOffset ) ;
100- } , [ ] ) ;
101-
10227 // 渲染树
10328 useEffect ( ( ) => {
10429 if ( ! svgRef . current || ! containerRef . current ) return ;
@@ -125,6 +50,81 @@ const TrieCanvas: React.FC<TrieCanvasProps> = ({ currentStep }) => {
12550 return ;
12651 }
12752
53+ // 计算树的布局 - 内联函数避免依赖问题
54+ const calculateLayout = ( node : VisualNode | null , depth : number = 0 , index : number = 0 , siblingCount : number = 1 ) : TreeNode | null => {
55+ if ( ! node ) return null ;
56+
57+ const horizontalSpacing = 70 ;
58+ const verticalSpacing = 80 ;
59+
60+ // 计算子节点
61+ const children : TreeNode [ ] = [ ] ;
62+ node . children . forEach ( ( child , i ) => {
63+ const childNode = calculateLayout ( child , depth + 1 , i , node . children . length ) ;
64+ if ( childNode ) children . push ( childNode ) ;
65+ } ) ;
66+
67+ // 计算当前节点位置
68+ let x = 0 ;
69+ if ( children . length > 0 ) {
70+ // 父节点居中于子节点
71+ const leftMost = children [ 0 ] . x ;
72+ const rightMost = children [ children . length - 1 ] . x ;
73+ x = ( leftMost + rightMost ) / 2 ;
74+ } else {
75+ x = ( index - ( siblingCount - 1 ) / 2 ) * horizontalSpacing ;
76+ }
77+
78+ return {
79+ id : node . id ,
80+ char : node . char ,
81+ isEnd : node . isEnd ,
82+ x,
83+ y : depth * verticalSpacing ,
84+ children,
85+ highlighted : currentStep . highlightedNodes . includes ( node . id ) ,
86+ } ;
87+ } ;
88+
89+ // 调整树的位置避免重叠 - 内联函数避免依赖问题
90+ const adjustTreePositions = ( root : TreeNode | null ) : TreeNode | null => {
91+ if ( ! root ) return null ;
92+
93+ const nodePositions : Map < number , number [ ] > = new Map ( ) ;
94+
95+ const collectPositions = ( node : TreeNode ) => {
96+ const level = Math . round ( node . y / 80 ) ;
97+ if ( ! nodePositions . has ( level ) ) {
98+ nodePositions . set ( level , [ ] ) ;
99+ }
100+ nodePositions . get ( level ) ! . push ( node . x ) ;
101+ node . children . forEach ( collectPositions ) ;
102+ } ;
103+
104+ const adjustNode = ( node : TreeNode , offset : number ) : TreeNode => {
105+ return {
106+ ...node ,
107+ x : node . x + offset ,
108+ children : node . children . map ( child => adjustNode ( child , offset ) ) ,
109+ } ;
110+ } ;
111+
112+ collectPositions ( root ) ;
113+
114+ // 找到最小x值,确保树居中
115+ let minX = Infinity ;
116+ let maxX = - Infinity ;
117+ nodePositions . forEach ( positions => {
118+ positions . forEach ( x => {
119+ minX = Math . min ( minX , x ) ;
120+ maxX = Math . max ( maxX , x ) ;
121+ } ) ;
122+ } ) ;
123+
124+ const centerOffset = - ( minX + maxX ) / 2 ;
125+ return adjustNode ( root , centerOffset ) ;
126+ } ;
127+
128128 let root = calculateLayout ( currentStep . trieSnapshot , 0 , 0 , 1 ) ;
129129 root = adjustTreePositions ( root ) ;
130130
@@ -269,7 +269,7 @@ const TrieCanvas: React.FC<TrieCanvasProps> = ({ currentStep }) => {
269269 } ) ;
270270 }
271271
272- } , [ currentStep , transform , calculateLayout , adjustTreePositions ] ) ;
272+ } , [ currentStep , transform ] ) ;
273273
274274 // 鼠标拖拽
275275 const handleMouseDown = ( e : React . MouseEvent ) => {
0 commit comments