mysterious_guy
mysterious_guy

Reputation: 435

d3.js code rendering only nodes and not links. Also need a way to add text to nodes and links

Below is how my json data looks in my html page:

var IDData = JSON.stringify([["node/105173", "node/38180995", "Agent", "Customer", "1379644.0", 1, 264.0, "1374903"], ["node/1061", "node/21373542", "Agent", "Customer", "530848.0", 1, 3000.0, "529502"]....]

The length of the array of array varies but but positioning of elements inside it is always the same.

Below is my d3.js code to render a force directed graph:

function createNodes (IDData) {
   var nodes = [{group:1, group: 1}]; 
   var links = [];
   IDData.forEach(function(item){
   nodes.push({id: item, group: 1})
   links.push({source: item, target: item, value: 1}) // ;
  });
var d3GraphData = {
   nodes: nodes,
   links: links
  } 
  return d3GraphData;
  };

function makeGraph (selector, d3GraphData) {
   var svg = d3.select(selector),
   width = +svg.attr("width"),
   height = +svg.attr("height");

   var color = d3.scaleOrdinal(d3.schemeCategory20);
   var simulation = d3.forceSimulation()
    .force("link", d3.forceLink().id(function(d) { return d.id; }))
    .force("charge", d3.forceManyBody())
    .force("center", d3.forceCenter(width / 2, height / 2));

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

 var node = svg.append("g")
   .attr("class", "nodes")
   .selectAll("circle")
   .data(d3GraphData.nodes)
   .enter()
   .append("circle")
   .attr("r", 5)
   .attr("fill", function(d) { return color(d.group); })
   .call(d3.drag()
   .on("start", dragstarted)
   .on("drag", dragged)
   .on("end", dragended)
 );

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

  simulation
    .nodes(d3GraphData.nodes)
    .on("tick", ticked);

 simulation.force("link")
    .links(d3GraphData.links);

 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("cx", function(d) { return d.x; })
    .attr("cy", function(d) { return 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;
     }

 $(document ).ready(function() {
     console.log(IDData);
     var galData = JSON.parse(IDData);
     var startnodes = [];
     var endnodes = [];
     var nodetype1 = [];
     var nodetype2 = [];
     var PayTime = [];
     var TXN_COUNT = [];
     var Total_Amt = [];
     var SendTime = [];

    galData.map(function(e,i){
     startnodes.push(e[0]);
     endnodes.push(e[1]);
     nodetype1.push(e[2]);
     nodetype1.push(e[3]);
     PayTime.push(e[4]);
     TXN_COUNT.push(e[5]);
     Total_Amt.push(e[6]);
     SendTime.push(e[7]);
    });
   var final_nodes = createNodes(startnodes,endnodes);                           
   makeGraph("#Network_graph",final_nodes);

    });

Also , I need var startnodes and var endnodes which are the node numbers ; var nodetype1 and var nodetype2 which are node types as node attributes. This needs to be displayed as texts on node and var PayTime , var TXN_COUNT, var Total_Amt, var SendTime as link attributes .

Right now I only see nodes and no links . Never used d3.js before. More of a back end guy.

Apologies if too much code is pasted.

Upvotes: 0

Views: 284

Answers (1)

mdml
mdml

Reputation: 22912

Your problem lies in how you convert your data into the format required by D3. Right now, you're trying to use the createNodes function to do this for you by passing in equal length lists of start/end (i.e. source/target) nodes for each link. But it's not quite working right since you are only taking the start nodes, so each link is connecting the same node and therefore is not visible.

I rewrote createNodes to create the nodes/links as D3 expects them. The only real trick is using d3.set() to create the list of nodes.

function createNodes (start_nodes, end_nodes) {
  var node_set = d3.set(); 
  var links = [];
  start_nodes.forEach(function(src, i){
    var tgt = end_nodes[i];
    node_set.add(src);
    node_set.add(tgt);
    links.push({source: src, target: tgt, value: 1});
  });
  var d3GraphData = {
    nodes: node_set.values().map(function(d){ return {id: d, group: 1} }),
    links: links
  } 
  return d3GraphData;
};

This is what you get in the output.

graph with links

(Note that there are a few typos in the code that you have to fix before it will compile.)

Upvotes: 1

Related Questions