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)