Question

I'm a beginner in javascript/d3, and came across a great network visualization I wanted to play around with.

I am looking to make the visualization dynamic, by adding links and their associated nodes at specified times.

To get me started, I first tried to keep all nodes displayed and simply add the links as they appear in the data file.

Stripping down the original html file, here is my attempt (adding the iterateLink() function, and slightly tweaking initializeGraph() ):

function iterateLinks() {
  for ( x = 0; x < zlinkz.length; x++ ) {
    setTimeout( function() {

      links.push(zlinkz[x]);
      restart();
    }, 2000);
  }
}

function initializeGraph(newGraph) {
  newNodes = [];
  newLinks = [];
  // We need a hash to fit the link structure of D3's force-directed layout
  nodeHash = {};

  zlinkz   = [];

  for ( x = 0; x < newGraph.nodes.length; x++ ) {
    newNodes.push(newGraph.nodes[x]);
    nodeHash[String(newGraph.nodes[x].id)] = x;
  }

  for ( x = 0; x < newGraph.links.length; x++ ) {
    newLinks.push({id: x, source: newGraph.nodes[nodeHash[newGraph.links[x].source]], target: newGraph.nodes[nodeHash[newGraph.links[x].target]], "cost": newGraph.links[x].cost, "weight": newGraph.links[x].invcost });
  }

  force = d3.layout.force()
      .size([width, height])
      .nodes(newNodes) // initialize with a single node
      .links(newLinks)
      .linkDistance(60)
      .charge(-60)
      .on("tick", tick);

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

  svg.append("rect")
      .attr("width", width)
      .attr("height", height)
      .attr("id","backgroundRect")
      .on("mousemove", mousemove);

  nodes = force.nodes();
  links = force.links();
  node = svg.selectAll(".node");
  link = svg.selectAll(".link");
  arrowhead = svg.selectAll(".link");

  cursor = svg.append("circle")
      .attr("transform", "translate(-100,-100)")
      .attr("class", "cursor")
      .attr("r", 1)
      .style("opacity", 0);

  restart();
  iterateLinks();
}

The complete code can be found on jsfiddle.

The function doesn't seem to iterate through the links despite my iterateLinks() function and doesn't display the links.

Do you know where I'm going wrong with the function, and how to solve it?

Any help is much appreciated! Thanks.

===== EDIT =====

Thanks to @Barnab and @AmeliaBR's help, I made the changes here and also included the adding nodes dynamically too.

Was it helpful?

Solution

Several things :

  • In your iterateLinks the x variable goes from 0 to 2 before the function in setTimeout is called, resulting in pushing always zlinkz[3] instead of your desired range of 0 to 2. I fixed it this way and it works the way you probably wanted it to :

    var it = 0;
    for (x = 0; x < zlinkz.length; x++) {
        setTimeout(function () {
            links.push(zlinkz[it]);
            restart();
            it++;
        }, 2000);
    }
    
  • There seems to be something wrong with your arrowhead drawing. I commented it out in this updated jsfiddle and if I understood what its function is I might be able to help you debug it :) If you uncomment it you'll see your links and nodes connected disappear because of a problem with .getElementById('directedCheck').checked

PS : I have written a tutorial on dynamic force-layout visualization on my blog and maybe it can give you some ideas for future endeavours.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top