vasturiano / 3d-force-graph

3D force-directed graph component using ThreeJS/WebGL
https://vasturiano.github.io/3d-force-graph/example/large-graph/
MIT License
4.67k stars 825 forks source link

How do I turn off `setTimeout` and `requestAnimationFrame` from the last render #639

Closed Leviash closed 1 year ago

Leviash commented 1 year ago

case

I have multiple types of data and I need to re-render the force-directed map when switching data.

const render = (data) => {
    if (graph) graph.graphData(null); // I wanna clear last render

    const graphData = JSON.parse(data); 
    graph = ForceGraph3D()(document.querySelector('#graph-3d'))
        .linkDirectionalParticles(2)
        .graphData(graphData)
        .linkDirectionalArrowLength(3.5) 
        .linkDirectionalArrowRelPos(1) 
        .linkDirectionalParticles('value')
        .linkDirectionalParticleSpeed((d) => d.value * 0.005)
        .nodeThreeObject((node) => {
            const sprite = new SpriteText(node.id);
            sprite.material.depthWrite = true; // make sprite background transparent
            sprite.color = node.color;
            sprite.textHeight = 2;
            return sprite;
        });
};

Error in browser developer tools

image

I don’t know how to turn off the previously enabled setTimeout and requestAnimationFrame. The more times the data is switched, the more laggy it becomes. So now, as a workaround, I pass null to the previous graph to avoid performance issues. However, this leads to errors like Cannot read properties of null (reading ‘nodes’) and Cannot read properties of null (reading ‘links’), and it doesn’t provide a real solution. Therefore, I would like to ask how to completely solve this problem?

Improving the code

dependencies.addEventListener('click', () => {
    if (flag == 2) {
        toggleMode(dependencies);
        flag = 1;
                let data = JSON.parse(sessionStorage.getItem('dependHash'));
        // render(data);
        graph.graphData(data); // load data
    }
});

devDependencies.addEventListener('click', () => {
    if (flag == 1) {
        toggleMode(devDependencies);
        flag = 2;
                let data = JSON.parse(sessionStorage.getItem('devPendHash'));
        // render(data);
        graph.graphData(data); // load data
    }
});

I changed the code so that Cannot read properties of null (reading ‘nodes’) and Cannot read properties of null (reading ‘links’) no longer give errors. But the problem of setTimeout and requestAnimationFrame remains.

image

Leviash commented 1 year ago

With the improved code, the performance does not degrade for multiple toggle. This tip about setTimeout and requestAnimationFrame has nothing to do with performance, except that multiple instances were created and not destroyed earlier.