Re-render nodes efficiently in D3 force-directed graph

280 views Asked by At

I have this:

    let nodeSelection = svg
        .selectAll("circle")
        .data(nodes)
        .enter()
        .append("g")
        .append("circle")
        .attr("r", d => d.size)
        .attr("fill", d => d.color)
        .attr("img", d => d.icon)
        .call(
            d3
                .drag()
                .on("start", dragStart)
                .on("drag", drag)
                .on("end", dragEnd)
        );

frequently (like 15x per second), there will be updates to various nodes in the graph. It would be way too expensive to re-render everything for every little update. I am trying to find the right call to update just a node, or just a link, using something like:

    svg
        .selectAll("circle")
        // .data(nodes) // probably don't want to provide new data?
        .enter()
        .attr(val++, val) // adding random-ass attributes to try
        .attr("fill", d => 'black')

is there some way to force a re-render of just parts of the graph?

1

There are 1 answers

2
Mark McClure On

If you want to change the colors of all the nodes to black, you could use

svg
  .selectAll('circle')
  .attr('fill', 'black')

You're correct that you probably don't want new data, unless you're expecting new points to appear. Note that

selection.enter()

refers to nodes entering from the addition of new data. Thus, the selection is guaranteed to be empty, if you don't have new data, which is one reason why your code won't work. In addition, the use of a function assign an attribute also assumes the presence of data, which is why we should use

.attr('fill', 'black')

rather than

.attr('fill', d => 'black')