I\'m still a beginner with JS + Python and I\'d be really happy to get your help on one problem. What I basically need to to is to pre-render a d3js visualizati
You can satisfy both requirements with CasperJS. Casper is a library that will use a headless browser to request a web page, which it can also programmatically interact with. A simple snippet of how to grab a screen shot goes something like this:
casper.start('http://ninjaPixel.io/', function() {
this.capture('page.png', undefined, {
format: 'png'
});
});
You can add a delay to this, to make sure that your force diagram is in a stable state when you take the screen shot. Casper can grab anything off the page, so if you display your computed node values in a html table, for example, tell Casper the id of that table and it can then grab it and save the values for you. You could even save the SVG object generated by your d3.js code.
This excellent graphic (by mbostock for nytimes) shows how to render a static graph layout in the DOM based on pre-computed positions. All the code is on the main html doc, so just "view source".
It first loads the data, and then calls ready
:
queue()
.defer(d3.json, "http://graphics8.nytimes.com/newsgraphics/2013/09/07/director-star-chart/ed9eaa686bc2e11f0657a78d9be292a730c0567a/graph.json")
.defer(d3.json, "http://graphics8.nytimes.com/newsgraphics/2013/09/07/director-star-chart/ed9eaa686bc2e11f0657a78d9be292a730c0567a/layout.json")
.await(ready);
If you dig look inside the .json files, you'll get a sense of how they chose to capture the graph data.
The ready
handler begins like this:
function ready(error, graph, positions) {
force
.nodes(graph.nodes)
.links(graph.links)
.on("tick", ticked)
.start();
if (positions) force.alpha(.0051);
....
You can see that it's initializing a force layout and setting its alpha()
to a very low number, signaling that the layout is essentially settled. As a result, the tick handler ticked()
probably only gets called one time, before the layout stops ticking due to the low alpha value.
However, also note that the setting of alpha to a very low value is conditional, depending on positions
being available. So if positions
were not pre-loaded and hence would be undefined
, the layout would tick repeatedly for a while until it settles on some positioning. This suggests to me that the same code rendering this static layout was also used — probably with some additional code but without the calculated positions
being loaded — during their process of exporting the positions. That's really quite clever of them(!).
The code that was used to gather and write the positions to file does not appear to be part of this page's source code, which makes sense, but you can hopefully come up with a way to do that within your project environment.