mysterious_guy mysterious_guy - 1 month ago 8
Javascript Question

A function in d3.js to create start and end nodes and node and link texts from a JSON source of varying size

My JSON data looks as below:

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.

I have the below jquery function that can iterate over such data:

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

galData.map(function(e,i){
startnodes.push(e[0]);
endnodes.push(e[1]);
startnodetype.push(e[2]);
endnodetype.push(e[3]);
PayTime.push(e[4]);
TXN_COUNT.push(e[5]);
Total_Amt.push(e[6]);
SendTime.push(e[7]);
});

var final_data =createNodes(startnodes,endnodes,startnodetype,endnodetype,PayTime,TXN_COUNT,Total_Amount,SendTime);
makeGraph("#Network_graph",final_data)

});


The data is then passed to the create node function which is as below:

function createNodes (start_nodes, end_nodes,startnodetype,endnodetype,PayTime,TXN_COUNT,Total_Amount,SendTime) {
var node_set = d3.set();
var links = [];
var nodetype = d3.set();
var link_Paytime = [];
var link_TXN_COUNT = [];
var link_Amt = [];
var link_SendTime = [];

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});
});

startnodetype.forEach(function(src,i){
var tgt_type = endnodetype[i];
nodetype.add(src);
nodetype.add(tgt_type);

});
var d3GraphData = {
nodes: node_set.values().map(function(d){ return {id: d, group: 1}}),
links: links,
nodetype: nodetype.values().map(function(d){return {id:d, group:1} })
link_Paytime: ?,
link_TXN_COUNT: ??,
link_Amt: ??,
link_SendTime: ??,
}
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); })
.on("mouseout",function() {div.html("Hover over the link");})
.on("mouseover",mouse_link); // calling mouseover function for links

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)
)
.on("mouseout",function() {div.html("Hover over the node");})
.on("mouseover",mouse_node); //calling the mouseover function for nodes

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;
}

function mouse_node(d){
div.html{"Node text is" + d.nodetype
.
function mouse_link(d){
div.html("Link text is " + d.link_PayTime,d.link_TXN_COUNT,d.link_Amt,d.link_SendTime);
}
};


Below should be the HTML:

<script src="http://code.jquery.com/jquery-1.11.1.min.js"></script>
<script src="http://d3js.org/d3.v4.min.js"></script>
<div id="graph"></div>
<div id="text">Hover over the link</div>
<div id= "text">Hover over the node</div>


Using this d3 gallery as a reference:
http://bl.ocks.org/mbostock/4062045 in the makeGraph code ;
I am able to add start nodes and end nodes and form links as can be seen above. I am also able to render graphs from them. But I also need a way to populate

nodetype,link_Paytime, link_TXN_COUNT,link_Amt, link_SendTime


and use them in d3GraphData which will be later used as "text" on nodes and links. This is my first project ever on d3.js.

Answer

below is the working piece of code that has text displayed on hovering over nodes and links:

https://jsfiddle.net/vishy1988/t6ycuoyo/21/

     var tooltip = d3.select("body")
  .append("div")
  .attr("class", "tooltip")
  .style("opacity", 0);

   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);
      .on('mouseover', function(d) {
          tooltip.transition()
            .duration(300)
            .style("opacity", .8);
          tooltip.html("<p/>Paytime:" + d.paytime + "<p/>Txn_count:" + d.txn_count + "<p/>Amount:" + d.Total_Amt + "<p/>SendTime:" + d.SendTime)

          .style("left", (d3.event.pageX) + "px")
            .style("top", (d3.event.pageY + 10) + "px");
        })
        .on("mouseout", function() {
          tooltip.transition()
            .duration(100)
            .style("opacity", 0);
        })
        .on("mousemove", function() {
          tooltip.style("left", (d3.event.pageX) + "px")
            .style("top", (d3.event.pageY + 10) + "px");
        });
    });

  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);
    })
    .on('mouseover', function(d) {
      tooltip.transition()
        .duration(300)
        .style("opacity", .8);
      tooltip.html(d.id + "<p/>type:" + d.type)
        .style("left", (d3.event.pageX) + "px")
        .style("top", (d3.event.pageY + 10) + "px");
    })
    .on("mouseout", function() {
      tooltip.transition()
        .duration(100)
        .style("opacity", 0);
    })
    .on("mousemove", function() {
      tooltip.style("left", (d3.event.pageX) + "px")
        .style("top", (d3.event.pageY + 10) + "px");
    })

  .call(d3.drag()
    .on("start", dragstarted)
    .on("drag", dragged)
    .on("end", dragended));

    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;
  }

}
Comments