TLDR;
When building a force directed graph based on multiple XML datasources, all the nodes appear stacked in the top left corner of the graph. Given there are no errors showing in console and all the nodes and links are correctly loaded afaik, what D3.js incorrect configuration could cause this behaviour?
Situation
Based on Mike Bostock's example of a Force-Directed Layout from XML https://bl.ocks.org/mbostock/1080941, I am loading multiple XML files using d3.queue and I am trying to display the force graph. When I am using one XML file the graph shows 1 node. However, when I am using multiple XML's the graph shows all the nodes in the top left corner. The console does not show any errors and all the required nodes and links objects are correctly loaded afaik.
Given
Edit: I have reduced code to a bare minimum to reproduce the problem. Four files are needed. Two small xml files, one json file and the html file.
FileList.json
[
"City.hbm.xml",
"Country.hbm.xml"
]
City.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="nl.sander.mieras.localhost.sakila.City" table="city" catalog="sakila">
<!-- removed for readability -->
</class>
</hibernate-mapping>
Country.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="nl.sander.mieras.localhost.sakila.Country" table="country" catalog="sakila">
<!-- removed for readability -->
</class>
</hibernate-mapping>
And the signifcantly reduced html file:
<!DOCTYPE html>
<meta charset="utf-8">
<style>
.link {
stroke: #ccc;
}
.node {
fill: #000;
stroke: #fff;
stroke-width: 2px;
}
</style>
<body>
<script src="//d3js.org/d3.v3.min.js"></script>
<script src="//d3js.org/d3-queue.v2.min.js"></script>
<script>
var width = 960,
height = 500;
var radius = d3.scale.sqrt()
.domain([0, 20000])
.range([0, 20]);
var force = d3.layout.force()
.charge(-240)
.linkDistance(40)
.size([width, height]);
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
d3.json("FileList.json", function (error, fileArray) {
var q = d3_queue.queue();
fileArray.forEach(function (d) {
q = q.defer(d3.xml, d);
});
q.await(analyze);
});
function analyze(error) {
if (error) {
console.log(error);
}
// skip 0 it's error variable
for (i = 1; i < arguments.length; i++) {
var xml = arguments[i];
var nodes = [];
var label = d3.select(xml).select("class").attr("table").charAt(0).toUpperCase() + d3.select(xml).select("class").attr("table").slice(1);
nodes.push({
"id": nodes.length,
"label": label
});
console.log(nodes);
node = nodes[0];
node.x = width / 2;
node.y = height / 2;
force
.nodes(nodes)
.start();
var node = svg.selectAll(".node")
.data(nodes)
.enter().append("circle")
.attr("class", "node")
.attr("r", 20)
.call(force.drag);
force.on("tick", function () {
node.attr("cx", function (d) {
return d.x;
})
.attr("cy", function (d) {
return d.y;
});
});
}
}
</script>
Question
Using one XML as data the graph looks like this...
Using multiple XML's as data the graph looks like this...
What part of the code is causing this behaviour? I have tried to configure the x and y coordinates with hard coded values, but regardless of my attempts, the nodes just appear as a 1/4 node in the top left corner.
Reproduce
I tried to make the issue ease to reproduce using jsfiddle, but I failed to get external sources to work regardless of my attempts based on the answers from How to add local json file in jsfiddle?
Full code on github gist:
https://gist.github.com/Weirdfishees/f1b19b43346a175bd214
and on github (small directory difference)