0

I can't multiple D3 force directed graphs to appear on one page, as they all pile into the same svg for whatever reason. I am out of ideas, and I have tried the top ideas online, which generally center around making sure you have a unique div to place each in, which I do.

I have divs with ids occurrences5, occurrences5...etc. So the loop should correctly find each div. The names of the JSON files are the same as the ids for each div.

var color = d3.scale.category20();

var occurences = ["occurrences3", "occurrences5", "occurrences10","occurrences20"];

for (var i = 0; i < occurences.length; i++) {
  var occurence = occurences[i];

  var svg = d3.select("#" + occurence).append("svg")
      .attr("width", width)
      .attr("height", height)
      .attr("id", "#" + occurence + "svg");

  d3.json(occurence + ".json", function(error, graph) {
    if (error) throw error;

    var force = d3.layout.force()
      .charge(-120)
      .linkDistance(30)
      .size([width, height]);

    force
        .nodes(graph.nodes)
        .links(graph.links)
        .start();

    var link = svg.selectAll(".link")
        .data(graph.links)
      .enter().append("line")
        .attr("class", "link")
        .style("stroke-width", function(d) { return Math.sqrt(d.value); });

    var node = svg.selectAll(".node")
        .data(graph.nodes)
      .enter().append("circle")
        .attr("class", "node")
        .attr("r", 5)
        .style("fill", function(d) { return color(d.group); })
        .call(force.drag);

    node.append("title")
        .text(function(d) { return d.name; });

    force.on("tick", function() {
      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; });
    });
  });
}})

enter image description here

P. Frank
  • 5,691
  • 6
  • 22
  • 50
Nick Anderson
  • 138
  • 2
  • 11
  • I don't think this is the cause of your problem, but you should not include the # symbol in your id: `.attr("id", "#" + occurence + "svg");` should be `.attr("id", occurence + "svg");`. The hash symbol is used in css selectors for finding an element by its id. – Kelvin Jan 25 '16 at 15:31
  • Very good point! That's a wonderful catch. – Nick Anderson Jan 26 '16 at 21:11

2 Answers2

1

You need to set svg within the callback function(error, graph) you pass to d3.json and not outside it

Reason: the callback function you pass to d3.json is called asynchronously i.e. it won't run nicely once per iteration as you're looping through the occurrences array. It appears all 4 callbacks are returning after that loop has finished and thus svg is set to the last value it had in that loop, thus everything's getting added to that svg element.

mgraham
  • 6,147
  • 1
  • 21
  • 20
0

If I separate the creation of each chart into their own function() blocks, it works. I got my answer from: D3 Dimple - How to show multiple dimple charts on same page?

However, you can separate into a function like so:

var occurences = ["occurrences3", "occurrences5", "occurrences10","occurrences20"];
occurences.forEach(function(entry) {
  draw(entry);
});
function draw(occurence) {...
Community
  • 1
  • 1
Nick Anderson
  • 138
  • 2
  • 11