diff --git a/network-onefile.html b/network-onefile.html
index 221f345..a5a4f2a 100644
--- a/network-onefile.html
+++ b/network-onefile.html
@@ -85,9 +85,8 @@
.attr("height", "800px")
.attr("width", "90%");
-var nodes = []
var g_edges = [];
-var box_width=200; // variable that determines box width and text length
+var box_width=100; // variable that determines box width and text length
function forceDirected() {
queue()
@@ -98,12 +97,17 @@
function createForceLayout(edges, group) {
var nodeHash = {};
+ var nodes = []
+ var labelAnchorLinks = []
+ var labelAnchors= []
// helper function to populate our node list
function add_node(name, group, edge_id) {
if ( nodeHash[name] === undefined ) {
nodeHash[name] ={id: name, group: group, edges: []} ;
nodes.push(nodeHash[name]);
+ labelAnchors.push({ node : nodeHash[name]})
+ labelAnchors.push({ node : nodeHash[name]})
}
nodeHash[name].edges.push(edge_id);
}
@@ -120,20 +124,58 @@
g_edges.push(edges[x]);
}
+for(var i = 0; i < nodes.length; i++) {
+ //labelAnchors.push({ node : nodeHash[i] });
+ //labelAnchors.push({ node : nodeHash[i] });
+ labelAnchorLinks.push({
+ source : i * 2,
+ target : i * 2 + 1,
+ weight : 1
+ });
+}
var weightScale = d3.scale.linear()
.domain(d3.extent(edges, function(d) {return d.weight}))
.range([.1,1]); // defaults to weight = 1
force = d3.layout.force()
- .charge(-1200) // #a How much each node pushes away each other, if set to a positive value, nodes will attract each other
+ .charge(-3000) // #a How much each node pushes away each other, if set to a positive value, nodes will attract each other
+ .gravity(1.00)
+ .friction(.50)
+ .linkDistance(50)
+// function(d,i) {
+// console.log(d,i);
+// return 30 + (i%3)*20;
+// }
+// )
.size([800,800]) // size of whole animation width and height
.nodes(nodes)
.links(edges)
.on("tick", forceTick); // #b “tick” events are fired continuously, running the associated function
- d3.select("svg").selectAll("line.link")
+// dense connection for labels, so they all repel each other
+
+force.start();
+
+force2 = d3.layout.force()
+ .nodes(labelAnchors)
+ .links(labelAnchorLinks)
+ .gravity(0.010)
+ .linkDistance(0)
+ .linkStrength(8)
+ .charge(-120) // #a How much each node pushes away each other, if set to a positive value, nodes will attract each other
+// function(d,i) {
+// console.log(d,i);
+// return 30 + (i%3)*20;
+// }
+// )
+ .size([800,800]) // size of whole animation width and height
+//.on("tick", forceTick);
+
+ force2.start()
+
+ var link = d3.select("svg").selectAll("line.link")
.data(edges, function (d) {return d.source.id + "-" + d.target.id}) // #c Key values for our nodes and edges will help when we update the network later
.enter()
.append("line")
@@ -141,13 +183,12 @@
.style("stroke-width", function(d) {return d.weight});
var nodeEnter = d3.select("svg").selectAll("g.node")
-.data(nodes, function (d) {return d.id})
+.data(force.nodes(), function (d) {return d.id})
.enter()
.append("g")
.attr("class", "node");
//console.log (nodeEnter); // shows all 27 nodes
-
nodeEnter.append("circle")
.attr("r", 5)
@@ -183,77 +224,133 @@
function (e,j) { return e.highlight });
}
+ var anchorLink = svg.selectAll("line.anchorLink").data(labelAnchorLinks)//.enter().append("svg:line").attr("class", "anchorLink").style("stroke", "#F00");
+
+ var anchorNode = svg.selectAll("g.anchorNode").data(force2.nodes()).enter().append("svg:g").attr("class", "anchorNode");
+ anchorNode.append("svg:circle").attr("r", 0).style("fill", "#FFF");
+ anchorNode.append("svg:text").text(function(d, i) {
+ console.log(d,i);
+ return i % 2 == 0 ? "" : d.node.id
+ }).style("fill", "#555").style("font-family", "Arial").style("font-size", 12);
// replace circle with rectangular
- nodeEnter.append('rect')
- .attr('x', -box_width/2)
- .attr('y', -5)
- .attr('rx', 5)
- .attr('height', '20')
- .attr('width' , box_width)
- .attr("class", function (d) {return d.group})
-
- .on("mouseover", function(d,i) {
- //d3.select(this).attr('title', d.id) svg:title takes care of this
- //console.log(d, d.edges);
- highlight(d.edges);
-
-
- // return d.value ;
-
- })
- .on("mouseout", function(d,i) {
- var rect = d3.select(this);
- //rect.style("class", function(
- highlight(d.edges, false);
-
-
- // return d.value ;
-
- })
-
- .on("click", function(d,i) {
- console.log(d, this.nid);
- highlight(d.edges, false);
- });
-
- ;
- nodeEnter.append("text")
- .style("text-anchor", "middle")
- .style("pointer-events", "none")
- .attr("y", 7)
-// .attr("dy", ".1em")
- .text(function(d) {return d.id})
- .attr("class", "text");
+ var updateLink = function() {
+ this.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;
+ });
+
+ }
+
+ var updateNode = function() {
+ this.attr("transform", function(d) {
+ return "translate(" + d.x + "," + d.y + ")";
+ });
+
+ }
- force.start(); // #d Initializing the network will start firing “tick” events as well as calculate the degree centrality of nodes
+
+ nodeEnter.call(force.drag);
+
+ //nodeEnter.append('rect')
+ // .attr('x', -box_width/2)
+ // .attr('y', -5)
+ // .attr('rx', 5)
+ // .attr('opacity', 0.5)
+ // .attr('height', '20')
+ // .attr('width' , box_width)
+ // .attr("class", function (d) {return d.group})
+ //
+ // .on("mouseover", function(d,i) {
+ // //d3.select(this).attr('title', d.id) svg:title takes care of this
+ // //console.log(d, d.edges);
+ // highlight(d.edges);
+ // })
+ // .on("mouseout", function(d,i) {
+ // var rect = d3.select(this);
+ // //rect.style("class", function(
+ // highlight(d.edges, false);
+ // })
+ //
+ // .on("click", function(d,i) {
+ // console.log(d, this.nid);
+ // highlight(d.edges, false);
+ // });
+ //
+ // ;
+
+
+ //nodeEnter.append("text")
+ //.style("text-anchor", "middle")
+ //.style("pointer-events", "none")
+ //.attr("y", 7)
+// //.attr("dy", ".1em")
+ //.text(function(d) {return d.id})
+ //.attr("class", "text");
+ force.start(); // #d Initializing the network will start firing “tick” events as well as calculate the degree centrality of nodes
function forceTick() {
- d3.selectAll("line.link")
- .attr("x1", function (d) {return d.source.x}) // #e The tick function updates the edge drawing code and node drawing code based on the newly calculated node positions
- .attr("x2", function (d) {return d.target.x})
- .attr("y1", function (d) {return d.source.y})
- .attr("y2", function (d) {return d.target.y});
-
-
- d3.selectAll("g.node")
- .attr("transform", function (d) {return "translate("+d.x+","+d.y+")"})
- }
+// force2.start();
+// d3.selectAll("line.link")
+// .attr("x1", function (d) {return d.source.x}) // #e The tick function updates the edge drawing code and node drawing code based on the newly calculated node positions
+// .attr("x2", function (d) {return d.target.x})
+// .attr("y1", function (d) {return d.source.y})
+// .attr("y2", function (d) {return d.target.y});
+//
+//
+// d3.selectAll("g.node")
+// .attr("transform", function (d) {return "translate("+d.x+","+d.y+")"})
+// }
+
+ force2.start();
+
+ nodeEnter.call(updateNode);
+
+ anchorNode.each(function(d, i) {
+ if(i % 2 == 0) {
+ d.x = d.node.x;
+ d.y = d.node.y;
+ } else {
+ var b = this.childNodes[1].getBBox();
+
+ var diffX = d.x - d.node.x;
+ var diffY = d.y - d.node.y;
+
+ var dist = Math.sqrt(diffX * diffX + diffY * diffY);
+
+ var shiftX = b.width * (diffX - dist) / (dist * 2);
+ shiftX = Math.max(-b.width, Math.min(0, shiftX));
+ var shiftY = 5;
+ this.childNodes[1].setAttribute("transform", "translate(" + shiftX + "," + shiftY + ")");
+ }
+ });
+
+
+ anchorNode.call(updateNode);
+
+ link.call(updateLink);
+ anchorLink.call(updateLink);
+ }
pi_wrap();
}
// helper function to drop all but the first set of characters which will fit
// inside the box, and adds and ellipsis to the end
function pi_wrap() {
- var text = d3.selectAll('text')[0];
+ var text = d3.selectAll('g.node text')[0];
text.forEach(function(x,i ) {
while (x.getBBox().width > box_width - 20) {
// keep dropping one letter off the end until we're down to 200 pixels
x.textContent = x.textContent.slice(0, x.textContent.length-2)
//x.textContent += "…"
- x.textContent += '\u2026'
+ x.textContent += '\u2026';
}
});
};