Reputation: 145
I'm making an application where a viewer can use a dat.gui menu to update their Three.js animation. Specifically, I'm using 3d-force-graph.
When the users makes a change, I do the following:
vertexControl
which changes the nodes of their new animation (e.g., color change).Simple example:
const settings = {
num : 5,
}
const gui = new dat.GUI();
gui.add(settings, 'num', 1, 10).step(1).onChange( function update(n) {
Graph.jsonUrl('new_json'+ n.toString() +'.json'); //a built-in of 3d-force-graph to update the .json
vertexControl() //Graph is now updated, so change the vertices
}
The problem: Before the Graph
object can be updated with the new .json, vertexControl
gets ahead of itself and executes. As a result, the desired changes to the nodes does not happen.
What I've tried 3d-force-graph has a method .refresh()
but that doesn't seem to do anything in my case. I've also tried callbacks and other solutions on StackOverflow which address questions along the lines of "How to make function2 execute after function1." They don't seem to work for this, which is very surprising and strange. What definitely works is setting up a ridiculous setTimeout
and guessing the milliseconds of when Graph
is updated. However, what I'm trying to do is extremely basic, so there has to be a sensible way to do this (right?).
Upvotes: 1
Views: 574
Reputation: 28497
The problem is that Graph.jsonUrl()
has to load that JSON asynchronously, but vertexControl()
is performed immediately, before the JSON has finished loading. I'm looking at the force-graph docs, and sadly there is no built-in way to perform a callback for when the JSON finishes loading. You might have to load the JSON yourself with THREE.FileLoader
so you can invoke your own callback after loading is complete:
// FileLoader can help you load JSON files yourself
var fileLoader = new THREE.FileLoader();
const settings = {
num : 5,
}
const gui = new dat.GUI();
gui.add(settings, 'num', 1, 10).step(1).onChange( function update(n) {
fileLoader.load(
'new_json'+ n.toString() +'.json',
// Callback for when JSON file has finished loading
function(response) {
// Convert response text to JSON object
const newData = JSON.parse(response);
// Pass resulting object to Graph
Graph.graphData(newData);
// Now you can run VertexControl
vertexControl();
}
);
}
The first argument to fileLoader.load
is the file path, and the second argument is the callback function to perform AFTER the file has finished loading. That way you can update your graph data first, and then run vertexControl
without having to wait further.
Upvotes: 1