vasturiano / react-force-graph

React component for 2D, 3D, VR and AR force directed graphs
https://vasturiano.github.io/react-force-graph/example/large-graph/
MIT License
2.19k stars 283 forks source link

Slowing animation speed (fps) #334

Closed joshraymo closed 2 years ago

joshraymo commented 2 years ago

First off, I want to thank you for the lovely library and the work that has gone into it. I'm currently implementing a Network explorer using the react-force-graph-2d library. The client wanted the user to not only be able to view a graph plotted statically, but to also be able to observe the force interactions within the data.

The issue is that the animation happens very fast, which is not optimal for a user who wants to observe the interactions at play between nodes.

I think that exposing a piece of the animation backend to allow for either a component prop or method to set the fps of the animation would be incredibly useful.

below is the solution that we came to for our own means, declaring 2 variables outside of the function:

let numTicks = 0; let animationRunning = false;

then including a function and useEffect within the function body to pause/resume animation using a timeout

function throttleAnimation() { if (!animationRunning || !fgRef.current) { numTicks = 0; return; } fgRef.current.pauseAnimation(); setTimeout(() => { fgRef.current.resumeAnimation(); throttleAnimation(); }, 50); numTicks += 1; } useEffect(() => { animationRunning = startAnimation; throttleAnimation(); }, [startAnimation]);

While this does work (and I'm posting it for anyone else who is having the same problem) it makes the animation somewhat choppy which is a shame as the libraries normal animation is incredibly smooth.

Again, thank you for a fantastic library, this is only a suggestion, and resource for others looking to do the same thing

vasturiano commented 2 years ago

Hi @joshraymo, thanks for reaching out, and I'm glad the lib is useful.

I don't believe there is an easier way to slow down the engine ticking other than what you're already doing. The typical use case is that the ticks should be rendered as soon as the layout computation is done, for each of the iterations. Also, because there is in fact no animation tweening the nodes positions in between ticks, the nodes "jump" from their previous to the new position instantly. This is probably what you perceive as "choppy", when the engine iterations are quick enough the nodes motion have a frame rate sufficiently high to be indistinguishable from a regular animation.

However, you can try a separate approach of trying to influence the inner dynamics of the force layout engine. For instance, by manipulating the d3AlphaDecay you can achieve a quicker or slower convergence into the nodes final state, by causing the influence of each of the forces to decay faster or slower. It's not exactly what you described as a "wait" time in between frames, but it may get you somewhat close to that effect.

joshraymo commented 2 years ago

HI!

Thank you for responding so quickly (and on a weekend too). What you're saying makes a lot of sense and I can see how that would be somewhat difficult. As far as our implementation goes the client ended up having no problem with the "choppiness" so we are moving forward with the product. While I was curious if there was a way to "smoothly" slow the animation I also wanted to just put our solution out there for anyone else who might be looking to do the same thing and hoped I could spare them a headache. I again thank you for all the work you've done on this library.

On Sat, Dec 11, 2021 at 8:32 PM Vasco Asturiano @.***> wrote:

Hi @joshraymo https://github.com/joshraymo, thanks for reaching out, and I'm glad the lib is useful.

I don't believe there is an easier way to slow down the engine ticking other than what you're already doing. The typical use case is that the ticks should be rendered as soon as the layout computation is done, for each of the iterations. Also, because there is in fact no animation tweening the nodes positions in between ticks, the nodes "jump" from their previous to the new position instantly. This is probably what you perceive as "choppy", when the engine iterations are quick enough the nodes motion have a frame rate sufficiently high to be indistinguishable from a regular animation.

However, you can try a separate approach of trying to influence the inner dynamics of the force layout engine. For instance, by manipulating the d3AlphaDecay https://github.com/vasturiano/react-force-graph#force-engine-configuration you can achieve a quicker or slower convergence into the nodes final state, by causing the influence of each of the forces to decay faster or slower. It's not exactly what you described as a "wait" time in between frames, but it may get you somewhat close to that effect.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/vasturiano/react-force-graph/issues/334#issuecomment-991817268, or unsubscribe https://github.com/notifications/unsubscribe-auth/AUWJLEUMIMCSCIEW5PDTD4DUQP3SZANCNFSM5JXYXIWQ . Triage notifications on the go with GitHub Mobile for iOS https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Android https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub.