I'm trying to pre-calculate the positions of the stable force directed graph using igraph and pass them into my d3.js graph. This is due to the size of the dataset I will be using which means I cannot rely on the client not to freeze if the full force calculation is done on client-side. I have the positions in JSON format and have used linear scales in order to make them useful in d3.js.
var positions =
{"positions": [{"x":"-68.824367374", "y": "-6.10824525755"},
{"x":"-80.8080803911", "y": "-3.38997541264"},
{"x":"6.75334817585", "y": "-49.6040729697"},
{"x":"14.6608797291", "y": "-81.8897019921"},
....
var force = d3.layout.force()
.charge(-100)
.linkDistance(3)
.size([width, height])
.nodes(data.nodes)
.links(data.links)
.start();
var posX = d3.scale.linear()
.range([0,960])
.domain([-125,120]);
var posY = d3.scale.linear()
.range([0,500])
.domain([-125,125]);
And this is the way I've tried to do it. I've experimented with px and py but the results are the same. It's as if this code is never ran. If I throw in a console.log
where seen below, the value does not get printed. This is regardless of where I put this code, be it before or after starting the force.
force.on("start", function() {
node
.data(positions.positions)
.attr("cx", function(d) {
console.log(posX(d.x));
return posX(d.x);
})
.attr("cy", function(d) {
return posY(d.y);
})
});
Why does the on start event not set the initial positions of my nodes? They seem to be initialised randomly still. Alternatively, what's a good way of pre-calculating the stable state of a d3.js force directed graph? I've had a look at doing it on Phantomjs but gave up.
Thank you for taking the time to read my question!
EDIT
Here is a dumbed down example: / If you run it a few times and pay attention to the starting positions of the nodes you can see they are randomly initialised.
I'm trying to pre-calculate the positions of the stable force directed graph using igraph and pass them into my d3.js graph. This is due to the size of the dataset I will be using which means I cannot rely on the client not to freeze if the full force calculation is done on client-side. I have the positions in JSON format and have used linear scales in order to make them useful in d3.js.
var positions =
{"positions": [{"x":"-68.824367374", "y": "-6.10824525755"},
{"x":"-80.8080803911", "y": "-3.38997541264"},
{"x":"6.75334817585", "y": "-49.6040729697"},
{"x":"14.6608797291", "y": "-81.8897019921"},
....
var force = d3.layout.force()
.charge(-100)
.linkDistance(3)
.size([width, height])
.nodes(data.nodes)
.links(data.links)
.start();
var posX = d3.scale.linear()
.range([0,960])
.domain([-125,120]);
var posY = d3.scale.linear()
.range([0,500])
.domain([-125,125]);
And this is the way I've tried to do it. I've experimented with px and py but the results are the same. It's as if this code is never ran. If I throw in a console.log
where seen below, the value does not get printed. This is regardless of where I put this code, be it before or after starting the force.
force.on("start", function() {
node
.data(positions.positions)
.attr("cx", function(d) {
console.log(posX(d.x));
return posX(d.x);
})
.attr("cy", function(d) {
return posY(d.y);
})
});
Why does the on start event not set the initial positions of my nodes? They seem to be initialised randomly still. Alternatively, what's a good way of pre-calculating the stable state of a d3.js force directed graph? I've had a look at doing it on Phantomjs but gave up.
Thank you for taking the time to read my question!
EDIT
Here is a dumbed down example: https://jsfiddle/xp0zgqes/ If you run it a few times and pay attention to the starting positions of the nodes you can see they are randomly initialised.
Share Improve this question edited Apr 19, 2016 at 12:13 Sebastian Smolorz asked Apr 18, 2016 at 22:14 Sebastian SmolorzSebastian Smolorz 5071 gold badge7 silver badges20 bronze badges 5- can you provide a working fiddle with what you have? – iulian Commented Apr 19, 2016 at 7:52
- Please see the revised question. – Sebastian Smolorz Commented Apr 19, 2016 at 12:13
- Really, noone? I'm kind of curious... – o-o Commented Apr 20, 2016 at 22:06
- 1 @o-o Please see my answer, hope it satisfies your curiosity :P – Sebastian Smolorz Commented Apr 21, 2016 at 18:25
- @SebastianSmolorz It does – thank you indeed. – o-o Commented Apr 21, 2016 at 22:00
1 Answer
Reset to default 8Really don't like answering my own question but I think this will be really useful. Firstly, (this may be specific in my case only) if the initial position data is ing from a different data object than the node/link data, it saves you having to bind to two data sources if you just bine it (or you can be smarter than me and just create the original json object with x and y positions). In my case:
for (var i = 0; i < data.nodes.length; i++){
data.nodes[i].x = posX(positions.positions[i].x);
data.nodes[i].y = posY(positions.positions[i].y);
data.nodes[i].newAttribute = value;
}
Thanks to the magic of JSON it is that easy to add new attributes to the data which is good e.g. if you want your nodes to be fixed.
The issue seems to be with the force.start()
call. If called when initialising the force like so:
var force = d3.layout.force()
.charge(-100)
.linkDistance(3)
.size([width, height])
.nodes(data.nodes)
.links(data.links)
.start();
the layout will randomly initialise the nodes by default. The way I found of getting around that is by adding an on tick event and start the force later.
var force = d3.layout.force()
.charge(-100)
.linkDistance(3)
.size([width, height])
.nodes(data.nodes)
.links(data.links)
.on("tick", tick);
force.start(); //Note, not chained
//Standard code that goes in the on.tick event
function tick() {
link.attr("x1", function(d) { return d.source.x; })
.attr("y1", function(d) { return d.source.y; })
.attr("x2", function(d) { return d.target.x; })
.attr("y2", function(d) { return d.target.y; });
node.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; });
}
And Voilà! We now have a fully functional force directed graph with initial positions set from json.
Working fiddle: https://jsfiddle/zbxbzmen/
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744171617a4561563.html
评论列表(0条)