d3.jsd3-force-directed

D3 force render speed


I'm having trouble finding the setting for how fast a d3-force graph renders. What I am asking about is not the number of iterations or alpha parameters, but the speed of the render cycle itself. What I am trying to accomplish is a instantaneous or instantaneous rendering of nodes on the componentDidUpdate hook.

My hook code (I believe this is answerable self-contained, but will add more ctx if not):

componentDidUpdate(prevProps: Readonly<IProps>, prevState: Readonly<IState>, snapshot?: any): void {
    const links : Array<Link> = [];
    this.props.nodes.forEach((n : any) => {
      if (!n.dependsOn) {
        return;
      }
      n.dependsOn.forEach((index : any) => {
        links.push({ source: index, target: n.id });
      });
    })
    this.simulation = forceSimulation(this.props.nodes)
    .force(
      "link",
      forceLink()
        .id((d : any) => d.id)
        .links(links)
        .distance(100)
        .strength(0.9)
    )
    .alpha(1)
    .alphaMin(0.1)
    .force("x", forceX(150).strength(0.5))
    .force("charge", forceManyBody().strength(0.01))
    .force(
      "y",
      forceY()
        .y(node => {
          return this._calcPath(node) * 150 - 50;
        })
        .strength((node : any) => {
          let dependedOn = this._nodeDependedOn(node);

          if (!dependedOn || node.dependsOn.length < 1) {
          return 3;
          }
          return 0;
        })
    )
    .force("collide", forceCollide(this.props.radius));

        this.simulation.on("tick", () =>
          this.setState({
            links: links,
            nodes: this.state.nodes
          })
        );
   }

Solution

  • I don't think there's any pause between applications of tick while the simulation is running so I don't think you can speed it up in the way that you suggest. What you can control is the number of steps per render using simulation.tick. If you take 300 steps right away, you should effectively generate the final layout right away.

    The implementation in this Observable notebook yields the following result:

    <div id="observablehq-viewof-steps_per_tick-39ec7ec3"></div>
    <div id="observablehq-animation-39ec7ec3"></div>
    
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@observablehq/inspector@5/dist/inspector.css">
    <script type="module">
    import {Runtime, Inspector} from "https://cdn.jsdelivr.net/npm/@observablehq/runtime@5/dist/runtime.js";
    import define from "https://api.observablehq.com/d/ebe85db08d365106@55.js?v=3";
    new Runtime().module(define, name => {
      if (name === "viewof steps_per_tick") return new Inspector(document.querySelector("#observablehq-viewof-steps_per_tick-39ec7ec3"));
      if (name === "animation") return new Inspector(document.querySelector("#observablehq-animation-39ec7ec3"));
    });
    </script>