1- /// <reference types="@react-three/fiber" />
21import React , { useRef , useMemo } from 'react' ;
32import { Canvas , useFrame } from '@react-three/fiber' ;
43import { OrbitControls , Line , Sphere , Text } from '@react-three/drei' ;
@@ -24,6 +23,11 @@ interface NetworkGraph3DProps {
2423
2524const NetworkNode : React . FC < { node : Node ; isHovered : boolean ; onHover : ( id : string | null ) => void } > = ( { node, isHovered, onHover } ) => {
2625 const meshRef = useRef < THREE . Mesh > ( null ) ;
26+ const group = useMemo ( ( ) => {
27+ const g = new THREE . Group ( ) ;
28+ g . position . set ( ...node . position ) ;
29+ return g ;
30+ } , [ node . position ] ) ;
2731
2832 useFrame ( ( ) => {
2933 if ( meshRef . current && isHovered ) {
@@ -43,7 +47,7 @@ const NetworkNode: React.FC<{ node: Node; isHovered: boolean; onHover: (id: stri
4347 const nodeSize = isHovered ? 0.3 : 0.2 ;
4448
4549 return (
46- < group position = { node . position } >
50+ < primitive object = { group } >
4751 < Sphere
4852 ref = { meshRef }
4953 args = { [ nodeSize , 32 , 32 ] }
@@ -69,7 +73,7 @@ const NetworkNode: React.FC<{ node: Node; isHovered: boolean; onHover: (id: stri
6973 { node . label }
7074 </ Text >
7175 ) }
72- </ group >
76+ </ primitive >
7377 ) ;
7478} ;
7579
@@ -78,7 +82,6 @@ const NetworkEdge: React.FC<{ start: [number, number, number]; end: [number, num
7882 new THREE . Vector3 ( ...start ) ,
7983 new THREE . Vector3 ( ...end )
8084 ] , [ start , end ] ) ;
81-
8285 return (
8386 < Line
8487 points = { points }
@@ -92,21 +95,18 @@ const NetworkEdge: React.FC<{ start: [number, number, number]; end: [number, num
9295
9396const NetworkGraph3D : React . FC < NetworkGraph3DProps > = ( { nodes, edges } ) => {
9497 const [ hoveredNode , setHoveredNode ] = React . useState < string | null > ( null ) ;
95-
9698 const nodeMap = useMemo ( ( ) => {
9799 const map = new Map < string , [ number , number , number ] > ( ) ;
98100 nodes . forEach ( node => map . set ( node . id , node . position ) ) ;
99101 return map ;
100102 } , [ nodes ] ) ;
101-
102103 return (
103104 < div className = "w-full h-[600px] bg-gray-900 rounded-lg overflow-hidden" >
104105 < Canvas camera = { { position : [ 0 , 0 , 10 ] , fov : 60 } } >
105106 < ambientLight intensity = { 0.4 } />
106107 < pointLight position = { [ 10 , 10 , 10 ] } intensity = { 1 } />
107108 < pointLight position = { [ - 10 , - 10 , - 10 ] } intensity = { 0.5 } />
108109 < spotLight position = { [ 0 , 10 , 0 ] } angle = { 0.3 } penumbra = { 1 } intensity = { 0.8 } />
109-
110110 { edges . map ( ( edge , index ) => {
111111 const start = nodeMap . get ( edge . source ) ;
112112 const end = nodeMap . get ( edge . target ) ;
@@ -115,7 +115,6 @@ const NetworkGraph3D: React.FC<NetworkGraph3DProps> = ({ nodes, edges }) => {
115115 }
116116 return null ;
117117 } ) }
118-
119118 { nodes . map ( ( node ) => (
120119 < NetworkNode
121120 key = { node . id }
@@ -124,7 +123,6 @@ const NetworkGraph3D: React.FC<NetworkGraph3DProps> = ({ nodes, edges }) => {
124123 onHover = { setHoveredNode }
125124 />
126125 ) ) }
127-
128126 < OrbitControls enableZoom = { true } enablePan = { true } autoRotate autoRotateSpeed = { 0.5 } />
129127 </ Canvas >
130128 </ div >
0 commit comments