Skip to content
Advertisement

networkD3 in R – Freeze forceNetwork()

Is there any way to freeze the layout with forceNetwork() in the {networkD3} lib?

This is taking me a lot of time, because of the number of nodes that my network has. I just need to stop the animation. I found something here, but didn’t solve my problem.

Here is part of my code:

p <- forceNetwork(Links = links, 
                  Nodes = nodes, 
                  Source = 'source', 
                  Target = 'target', 
                  NodeID = 'name',
                  Group = 'group', 
                  Value = "value",
                  Nodesize = "size",
                  radiusCalculation = JS("d.nodesize"),
                  zoom = TRUE, 
                  arrows = FALSE,
                  linkWidth = JS("function(d){return d.value;}"),
                  linkDistance = JS("function(d){return d.value*10}"),
                  charge = gravity,
                  opacity = 0.95,
                  fontSize = 24,
                  linkColour = "#424242"
)

customJS <- 
  "function() { 
    d3.selectAll('.node text').style('fill', 'white').attr('stroke-width', '.1px').attr('stroke', '#3f3f3f');
    d3.select('body').style('background-color', '#15171a');
    d3.layout.force().tick();
    d3.layout.force().stop();
  }"


g <- htmlwidgets::onRender(p, customJS)
g

Advertisement

Answer

You could stop the simulation, run forward through the ticks without updating the positions (effectively the “animation”), and then restart the simulation so the nodes’ positions are updated…

library(networkD3)

p <-
  forceNetwork(
    Links = MisLinks,
    Nodes = MisNodes,
    Source = "source",
    Target = "target",
    Value = "value",
    NodeID = "name",
    Group = "group",
    opacity = 0.4,
    zoom = TRUE
  )

customJS <- '
  function() {
    simulation = this;
    simulation.stop();
    for (var i = 0; i < 300; ++i) simulation.tick();
    simulation.nodes().forEach( function(d,i) {
      d.cx = d.x;
      d.cy = d.y;
    });
    simulation.restart();
  }
'

htmlwidgets::onRender(p, customJS)

I’ve also been working on a successor to {networkD3} that can do this easily (although by default it uses canvas instead of SVG, and therefore it can handle much more data, even with the animation)…

library(network.r2d3)
url <- "https://gist.githubusercontent.com/mbostock/ad70335eeef6d167bc36fd3c04378048/raw/df541a01e850c6073ece4516fcd74ea1bae080ab/miserables.json"
force_network(url, plot_static = TRUE)
User contributions licensed under: CC BY-SA
8 People found this is helpful
Advertisement