is there a way to keep the gentle floating movement after the initial graph animation?
Jing1524 opened this issue · comments
I'm working on a project using a basic graph visualization example. Implementing it has been straightforward for the most part. However, I'm struggling with a specific aspect: I want the nodes in the graph to continue floating after the initial render, similar to an effect seen in a Three.js example floating
Here are the methods I've tried so far:
-
Adjusting cooldownTime to slow down the node movement, hoping to maintain a floating effect. Unfortunately, this hasn't worked as expected.
-
Attempting to reheat the simulation. This approach causes the graph to re-render and results in the nodes floating off the screen.
-
Using useEffect to monitor and update each node's location. While this gets me closer to the desired effect, I'm still unable to achieve the smoothness of the floating animation, and I can't prevent the nodes from floating off the screen.
Ideally, I'd like a solution that provides an option to toggle between continuous floating and allowing the graph to gradually come to a stop.
Additional context
below is a quick version of what i have for context, the node stops completely towards the end.
codesandbox
@Jing1524 you can try setting the node's velocities (via v*
attributes) instead of their positions. This will probably get you closer to what you have in mind. And possibly it helps too to set d3VelocityDecay
and d3AlphaDecay
to 0
.
Take a look at this example.
react-force-graph/example/collision-detection/index.html
Lines 49 to 53 in 0fd8cac
@vasturiano thank you so much for the quick response! will try it out! :)
@vasturiano hey sorry to bother you again.
I just spend a few hours working on it again, but having a hard time to get it to work, feels like I'm missing something still,
i did manage to have the node keep moving, but the resulting movement is way too dramatic. I'm attaching my code and sandbox to show you the currently result. wondering if you could help.
here is the current result
Below useEffect is doing the heavy lift for the "floating" movement.
useEffect(() => {
graphData.nodes.forEach((node) => {
const initialColor = "#E4CDC6";
const targetColor = "#a7715f";
setNodeTransition((prev) => ({ ...prev, [node.id]: initialColor }));
setTimeout(() => {
animateColorTransition(node.id, initialColor, targetColor, 500); // Transition over 2 seconds
}, Math.random() * 5000 + 1000); // Random interval between 3s and 8s
});
graphData.nodes.forEach((node) => {
node.vx = Math.random() * 2 - 1;
node.vy = Math.random() * 2 - 1;
node.vz = Math.random() * 2 - 1;
});
const BOUNDING_BOX_SIZE = 10;
const enforceBoundingBox = () => {
graphData.nodes.forEach((node) => {
if (Math.abs(node.x) > BOUNDING_BOX_SIZE) node.vx *= -1;
if (Math.abs(node.y) > BOUNDING_BOX_SIZE) node.vy *= -1;
if (Math.abs(node.z) > BOUNDING_BOX_SIZE) node.vz *= -1;
});
};
const interval = setInterval(enforceBoundingBox, 1000);
return () => clearInterval(interval);
}, [graphData.nodes]);
return (
<ForceGraph3D
ref={forceGraphRef}
width={width}
height={height}
graphData={graphData}
backgroundColor="#ffffff"
showNavInfo={false}
nodeColor={(node) => nodeTransition[node.id] || "#E4CDC6"}
nodeOpacity={1}
linkColor={(d) => (d.type === "OK" ? "#E4CDC6" : "#E4CDC6")}
linkOpacity={0.75}
enableNavigationControls={false}
d3AlphaDecay={0}
d3VelocityDecay={0}
/>
)