diff --git a/src/components/Universe/Graph/Cubes/SelectionDataNodes/index.tsx b/src/components/Universe/Graph/Cubes/SelectionDataNodes/index.tsx
index bac65beb7..99fe4c07b 100644
--- a/src/components/Universe/Graph/Cubes/SelectionDataNodes/index.tsx
+++ b/src/components/Universe/Graph/Cubes/SelectionDataNodes/index.tsx
@@ -116,9 +116,17 @@ export const SelectionDataNodes = memo(() => {
return (
<>
- {selectionGraphData?.nodes.map((node) => (
+ {selectionGraphData?.nodes.map((node, index) => (
-
+
))}
diff --git a/src/components/Universe/Graph/Cubes/Text/index.tsx b/src/components/Universe/Graph/Cubes/Text/index.tsx
index 56ebf1079..f0c06a83a 100644
--- a/src/components/Universe/Graph/Cubes/Text/index.tsx
+++ b/src/components/Universe/Graph/Cubes/Text/index.tsx
@@ -1,7 +1,7 @@
import { Billboard, Plane, Svg, Text } from '@react-three/drei'
-import { useFrame } from '@react-three/fiber'
+import { useFrame, useThree } from '@react-three/fiber'
import gsap from 'gsap'
-import { memo, useEffect, useRef } from 'react'
+import { memo, useRef } from 'react'
import { Mesh, MeshBasicMaterial, Vector3 } from 'three'
import { Icons } from '~/components/Icons'
import { useTraceUpdate } from '~/hooks/useTraceUpdate'
@@ -18,6 +18,8 @@ type Props = {
color: string
hide?: boolean
ignoreDistance: boolean
+ scale: number
+ index: number
}
function splitStringIntoThreeParts(text: string): string {
@@ -38,13 +40,22 @@ function splitStringIntoThreeParts(text: string): string {
return `${firstPart}\n${secondPart}\n${thirdPart}`
}
+const offset = { x: 20, y: 20 }
+
export const TextNode = memo(
(props: Props) => {
- const { node, hide, ignoreDistance, color } = props
+ const { node, hide, ignoreDistance, color, index } = props
+ const simulation = useGraphStore((s) => s.simulation)
+ const positionAnimationRef = useRef(null)
+ const scaleAnimationRef = useRef(null)
+
+ const finishedSimulationCircle = useRef(false)
const svgRef = useRef(null)
const ringRef = useRef(null)
const circleRef = useRef(null)
+ const wrapperRef = useRef(null)
+ const { camera: perspectiveCamera, size } = useThree()
useTraceUpdate(props)
@@ -89,30 +100,69 @@ export const TextNode = memo(
}
if (circleRef.current) {
- circleRef.current.visible = false
+ circleRef.current.visible = true
}
- checkDistance()
- })
-
- useEffect(() => {
- if (!ringRef.current) {
- return
+ if (finishedSimulationCircle.current) {
+ checkDistance()
}
- gsap.fromTo(
- ringRef.current.scale, // Target
- { x: 1, y: 1, z: 1 }, // From values
- {
- x: 2,
- y: 2,
- z: 2, // To values
- duration: 1.5, // Animation duration
- yoyo: true,
- repeat: 1,
- },
- )
- }, [ringRef])
+ if (wrapperRef.current && simulation) {
+ const simulationNode = simulation.nodes()[index]
+
+ if (!simulationNode) {
+ return
+ }
+
+ if (!finishedSimulationCircle.current) {
+ // Define the NDC coordinates for the fixed position
+ const ndc = new Vector3(
+ -1 + (offset.x * 2) / size.width, // Adjust for left offset
+ 1 - (offset.y * 2) / size.height, // Adjust for top offset
+ 0, // Near clipping plane
+ )
+
+ // Convert NDC to world space
+ const worldPosition = ndc.unproject(perspectiveCamera)
+
+ // Maintain a fixed distance from the camera
+ const distanceFromCamera = 5
+ const direction = worldPosition.sub(perspectiveCamera.position).normalize()
+ const fixedPosition = perspectiveCamera.position.clone().add(direction.multiplyScalar(distanceFromCamera))
+
+ wrapperRef.current.position.copy(fixedPosition)
+
+ // Store the largest dimension as the "size" of the mesh
+
+ wrapperRef.current.scale.set(0.1, 0.1, 0.1)
+
+ wrapperRef.current.visible = false
+ }
+
+ if (simulationNode.fx && !finishedSimulationCircle.current) {
+ wrapperRef.current.visible = true
+ finishedSimulationCircle.current = true
+ positionAnimationRef?.current?.kill()
+ scaleAnimationRef?.current?.kill()
+
+ positionAnimationRef.current = gsap.to(wrapperRef.current.position, {
+ x: simulationNode.fx, // Destination X coordinate
+ y: simulationNode.fy, // Destination Y coordinate
+ z: simulationNode.fz, // Destination Z coordinate
+ duration: 4, // Animation duration in seconds
+ ease: 'power2.in', // Easing function
+ })
+
+ scaleAnimationRef.current = gsap.to(wrapperRef.current.scale, {
+ x: 1, // Destination X coordinate
+ y: 1, // Destination Y coordinate
+ z: 1, // Destination Z coordinate
+ duration: 4.5, // Animation duration in seconds
+ ease: 'power2.in', // Easing function
+ })
+ }
+ }
+ })
const primaryColor = normalizedSchemasByType[node.node_type]?.primary_color
const primaryIcon = normalizedSchemasByType[node.node_type]?.icon
@@ -132,17 +182,20 @@ export const TextNode = memo(
}
return (
-
-
-
-
-
-
-
- {node.properties?.image_url && texture ? (
-
-
+
+
+
+
+
+
+
+
+
+ {node.properties?.image_url && texture ? (
+
+
+
+ ) : (
+
- ) : (
-
-
+ )}
+
+ {sanitizedNodeName && (
+
+ {splitStringIntoThreeParts(sanitizedNodeName)}
+
+ )}
+
+
+
)
},
(prevProps, nextProps) =>
diff --git a/src/components/Universe/Graph/Cubes/index.tsx b/src/components/Universe/Graph/Cubes/index.tsx
index 3c677261e..4da4b98be 100644
--- a/src/components/Universe/Graph/Cubes/index.tsx
+++ b/src/components/Universe/Graph/Cubes/index.tsx
@@ -142,22 +142,20 @@ export const Cubes = memo(() => {
>
- {data?.nodes.map((node: NodeExtended) => {
+ {data?.nodes.map((node: NodeExtended, index) => {
const hide = !!selectedNode && (relativeIds.includes(node.ref_id) || selectedNode.ref_id === node.ref_id)
const color = COLORS_MAP[nodeTypes.indexOf(node.node_type)] || colors.white
return (
-
-
-
-
-
+
)
})}
diff --git a/src/components/Universe/Graph/index.tsx b/src/components/Universe/Graph/index.tsx
index c1c78840c..7a37e9354 100644
--- a/src/components/Universe/Graph/index.tsx
+++ b/src/components/Universe/Graph/index.tsx
@@ -10,7 +10,6 @@ import { Connections } from './Connections'
import { Cubes } from './Cubes'
import { Earth } from './Earth'
import { LoadingNodes } from './LoadingNodes'
-import { Particles } from './Particles/index'
import { NodeDetailsPanel } from './UI'
export type LinkPosition = {
@@ -88,22 +87,24 @@ export const Graph = () => {
cameraSettled.current = true
}
}
+ })
+
+ simulation.on('end', () => {
+ const nodesVector = simulation.nodes().map((i: NodeExtended) => {
+ // eslint-disable-next-line no-param-reassign
+ i.fx = i.x
+ // eslint-disable-next-line no-param-reassign
+ i.fy = i.y
+ // eslint-disable-next-line no-param-reassign
+ i.fz = i.z
+
+ return new Vector3(i.x, i.y, i.z)
+ })
if (groupRef.current) {
- const gr = groupRef.current.getObjectByName('simulation-3d-group__nodes') as Group
const grPoints = groupRef.current.getObjectByName('simulation-3d-group__node-points') as Group
const grConnections = groupRef.current.getObjectByName('simulation-3d-group__connections') as Group
- if (gr) {
- gr.children.forEach((mesh, index) => {
- const simulationNode = simulation.nodes()[index]
-
- if (simulationNode) {
- mesh.position.set(simulationNode.x, simulationNode.y, simulationNode.z)
- }
- })
- }
-
if (grPoints) {
grPoints.children[0].children.forEach((mesh, index) => {
const simulationNode = simulation.nodes()[index]
@@ -114,10 +115,6 @@ export const Graph = () => {
})
}
- if (simulation.alpha() > 1) {
- return
- }
-
if (grConnections) {
linksPositionRef.current.clear()
@@ -174,31 +171,10 @@ export const Graph = () => {
})
}
}
- })
-
- simulation.on('end', () => {
- const nodesVector = simulation.nodes().map((i: NodeExtended) => {
- // eslint-disable-next-line no-param-reassign
- i.fx = i.x
- // eslint-disable-next-line no-param-reassign
- i.fy = i.y
- // eslint-disable-next-line no-param-reassign
- i.fz = i.z
-
- return new Vector3(i.x, i.y, i.z)
- })
const boundingBox = new Box3().setFromPoints(nodesVector)
- const boundingSphere = new Sphere()
-
- boundingBox.getBoundingSphere(boundingSphere)
-
- const sphereRadius = boundingSphere.radius
-
- setGraphRadius(sphereRadius * 1.5)
-
- cameraSettled.current = false
+ console.log(boundingBox)
})
}, [dataInitial, simulation, setGraphRadius, normalizedSchemasByType])
@@ -210,7 +186,6 @@ export const Graph = () => {
{graphStyle === 'earth' && }
-
{(isLoadingNew || isFetching) && }