score:0

I'm posting this there in case someone else had the same problem. I solved my problem by breaking up the drawGraph function into smaller widgets.

I moved the following to the parent scope.

var svg = d3.select("svg"),
      w = +svg.attr("width"),
      h = +svg.attr("height),
      node,
      link;

var simulation = d3.forceSimulation(nodes)
    .force("link", d3.forceLink().id(function(d) { return d.id; }).distance(60))
    .force("charge", d3.forceManyBody())
    .force("center", d3.forceCenter(w / 2, h / 2))
    .force("attraceForce",d3.forceManyBody().strength(-900));

var color = d3.scaleOrdinal(d3.schemeCategory20);

Then within the drawGraph function I made the following changes.

function drawGraph(nodes,links){
   var g = svg.append("g");
   link = g.selectAll(".link").data(links,function(d){ return d.target.id; })
   link = link.enter()
        .append("line")
        .attr("class","link")
        .style("stroke-width", function(d) { return d.value; })
        .style("stroke", "#999")

   node = g.selectAll(".node").data(nodes,function(d){ return d.id; })
   node = node.enter()
        .append("g")
        .attr("class","node")
        .call(d3.drag()
          .on("start", dragstarted)
          .on("drag", dragged)
          .on("end", dragended))
   node.append("circle").attr("r", 14).attr("fill",function(d){return color(d.group);})
   node.append("text").attr("dy", -15)
       .text(function(d){ return d.id; })
       .attr("text-anchor","middle")
       .style("fill", "#555");

   node.append("image")
       .attr("xlink:href",function(d){
          var type = d.type,
          typeIcon = "",
          switch(type){
            //assigns an image based on the subject type person, address, phone, ect.
           }
       return typeIcon;
      })
      .attr("x", -8)
      .attr("y", -8)
      .attr("height", 16)
      .attr("width", 16);

 simulation.nodes(nodes).on("tick", ticked);
 simulation.force("link").links(links);

 function zoom_actions(){
    g.attr("transform", d3.event.transform);
 };

 var zoom_handler = d3.zoom()
  .scaleExtent([1/4, 4])
  .on("zoom", zoom_actions);

 svg.call(zoom_handler).call(zoom_handler.transform, d3.zoomIdentity.scale(0.9,0.9));

zoom_handler(svg);

};

function ticked() {
 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("transform", function(d) { 
           return "translate("+ d.x + ", " + d.y + ")"; 
      });
};

 function dragstarted(d) {
  if (!d3.event.active) simulation.alphaTarget(0.3).restart();
  d.fx = d.x;
  d.fy = d.y;
}

function dragged(d) {
  d.fx = d3.event.x;
  d.fy = d3.event.y;
}

function dragended(d) {
  if (!d3.event.active) simulation.alphaTarget(0);
  d.fx = null;
  d.fy = null;
}

I then added the following function which is used to setup the data and draw the graph.

function formatGraphData(relationships){
 nodes = relationships.nodes;
 links = relationships.links;
 simulation.alpha(0.5).restart(); //<- needed to restart simulation and position nodes
 drawGraph(nodes,links);
}

Then the ajax calls were updated to use formatGraphData instead of drawGraph.

I added the following to my css file

.links line{
 stroke: #999;
}
.nodes circle{
 stroke: #fff;
 stroke-width: 1.5px;
}

Related Query

More Query from same tag