Skip to content

Instantly share code, notes, and snippets.

@daohodac
Last active August 29, 2015 14:09
Show Gist options
  • Save daohodac/c6f2058d81bd94a130e5 to your computer and use it in GitHub Desktop.
Save daohodac/c6f2058d81bd94a130e5 to your computer and use it in GitHub Desktop.
dynamically add some simple force directed labels to elements
<!DOCTYPE html>
<meta charset="utf-8">
<body>
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
<svg width="300px" height="200px">
<rect stroke="black" fill="lightgrey" x="0" y="0" width="300px" height="200px"/>
</svg>
<button id="addBtn">ADD</button>
<script type="text/javascript">
console.log("init all")
var airports = [];
var labels = [];
var nodes = []
var labelLinks = [];
for (var i=1; i<6; i++) {
for (var j=1; j<6; j++) {
var im1 = i-1;
var jm1 = j-1;
addAirport("id"+i+j, im1*60+30, jm1*40+20);
}
}
var addCnt = 0;
function addAirport(id, x, y) {
var airport = {x:x, y:y, fixed:true};
var label = {x:x, y:y, name:id, id:id}
airports.push(airport)
labels.push(label)
var idx = nodes.length;
nodes.push(airport)
nodes.push(label)
labelLinks.push({source: idx, target: idx+1, target_id: "#"+id});
}
d3.select("#addBtn").on('click', function() {
addCnt++;
addAirport("a"+addCnt, 120, 120);
init();
nodesForce.start();
});
var tick = function(a) {
circles
.attr("cx", function(d) {return d.x; })
.attr("cy", function(d) { return d.y; });
texts
.attr("x", function(d) {return d.x; })
.attr("y", function(d) { return d.y; });
lines
.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;})
lines.each(function (d,i) {
var lb = d.target;
var cc = d.source;
var targetD3 = d3.select(d.target_id);
var bbox = targetD3.node().getBBox();
var diffX = lb.x - cc.x;
var diffY = -lb.y + cc.y;
shiftX=Math.max(0, Math.min(bbox.width, -diffX));
shiftY=Math.max(0, Math.min(bbox.height, -diffY));
var translate = "translate(" + -shiftX + "," + shiftY + ")";
targetD3.attr("transform", translate);
});
}
var nodesForce = d3.layout.force()
.size([300, 200])
.nodes(nodes)
.links(labelLinks)
.linkStrength(1)
.friction(0.8)
.gravity(0)
.distance(20)
.charge(-10)
.on("tick", tick);
function dragstart(d) {
d3.select(this).classed("fixed", d.fixed = true);
}
var drag = nodesForce.drag()
.on("dragstart", dragstart);
var circles, texts, lines;
var init = function () {
//create the circles
d3.select('svg').selectAll('circle').data(airports)
.enter().append('circle')
.attr('cx', function(d) {return d.x;})
.attr('cy', function(d) {return d.y;})
.attr('r', 5)
.attr('fill', function(d) {
if (d.fixed) return 'red'; else return 'grey';
})
.call(drag);
circles = d3.select('svg').selectAll('circle');
d3.select('svg').selectAll('text').data(labels)
.enter().append('text')
.attr('x', function(d) {return d.x;})
.attr('y', function(d) {return d.y;})
.text(function(d) {return d.name;})
.attr('id', function(d) {return d.id;})
.call(drag);
texts = d3.select('svg').selectAll('text')
d3.select('svg').selectAll('line').data(labelLinks)
.enter().append('line')
.attr('x1', function(d) {return nodes[d.source].x;})
.attr('y1', function(d) {return nodes[d.source].y;})
.attr('x2', function(d) {return nodes[d.target].x;})
.attr('y2', function(d) {return nodes[d.target].y;})
.attr('stroke', 'grey');
lines = d3.select('svg').selectAll('line');
}
init();
nodesForce.start();
</script>
</body>
@daohodac
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment