|
<!DOCTYPE html> |
|
<html lang="en"> |
|
|
|
<head> |
|
<meta charset="utf-8"> |
|
<script src="https://d3js.org/d3.v4.min.js" type="text/javascript"></script> |
|
<style> |
|
line.node-link, path.node-link { |
|
fill: none; |
|
stroke: black |
|
} |
|
circle.node { |
|
fill: white; |
|
stroke: black |
|
} |
|
circle.node+text { |
|
text-anchor: middle; |
|
} |
|
text { |
|
font-family: sans-serif; |
|
pointer-events: none; |
|
} |
|
</style> |
|
</head> |
|
|
|
<body> |
|
<script> |
|
|
|
var width = 500, |
|
height = 500; |
|
|
|
var dataset = { |
|
"nodes":[ |
|
{"id":0,"name":"0"}, |
|
{"id":1,"name":"1"}, |
|
{"id":2,"name":"2"}, |
|
{"id":3,"name":"3"}, |
|
{"id":4,"name":"4"}, |
|
{"id":5,"name":"5"}, |
|
{"id":6,"name":"6"}, |
|
{"id":7,"name":"7"}, |
|
{"id":8,"name":"8"}, |
|
{"id":9,"name":"9"} |
|
], |
|
"links":[ |
|
{"id":1,"source":1,"target":0}, |
|
{"id":2,"source":2,"target":0}, |
|
{"id":3,"source":3,"target":0}, |
|
{"id":4,"source":4,"target":0}, |
|
{"id":5,"source":5,"target":0}, |
|
{"id":6,"source":6,"target":0}, |
|
{"id":7,"source":7,"target":0}, |
|
{"id":8,"source":8,"target":0}, |
|
{"id":9,"source":9,"target":0,} |
|
] |
|
}; |
|
|
|
var nodes = dataset.nodes |
|
var links = dataset.links |
|
|
|
var simulation = d3.forceSimulation() |
|
.force("link", d3.forceLink() |
|
.id(function(d,i) { return i }) |
|
.distance(100) |
|
) |
|
.force("charge", d3.forceManyBody().strength(function(d,i) { return i==0 ? 10*-500 : -500 })) |
|
.force("center", d3.forceCenter(width / 2, height / 2)); |
|
|
|
simulation |
|
.nodes(nodes) |
|
|
|
simulation.force("link") |
|
.links(links) |
|
|
|
for (var i = nodes.length * nodes.length; i > 0; --i) simulation.tick(); |
|
|
|
var svg = d3.select("body").append("svg") |
|
.attr("width", width) |
|
.attr("height", height); |
|
|
|
// Draw curved lines connecting node to center |
|
//var lines = svg.selectAll("path") |
|
//.data(links).enter().append("path") |
|
//.attr("class", function(d,i) { return "node-link node-link-"+ d.id.toString()}) |
|
//.attr("d", function(d) { |
|
//var dx = d.target.x - d.source.x, |
|
//dy = d.target.y - d.source.y, |
|
//dr = Math.sqrt(dx * dx + dy * dy); |
|
//return "M" + |
|
//d.source.x + "," + |
|
//d.source.y + "A" + |
|
//dr + "," + dr + " 0 0,1 " + |
|
//d.target.x + "," + |
|
//d.target.y; |
|
//}); |
|
|
|
var gnodes = svg.selectAll('g.gnode') |
|
.data(nodes).enter().append('g') |
|
.attr("class", function(d,i) { return "gnode node-"+ d.id.toString()}) |
|
.attr("transform", function(d,i) { |
|
return "translate(" + d.x + "," + d.y + ")"; |
|
}); |
|
|
|
d3.select(".node-0").classed("centered", true) |
|
|
|
var node = gnodes.append("circle") |
|
.attr("r", 25) |
|
.attr("class", "node") |
|
.on("mouseenter", function(d) { |
|
node.transition().duration(100).attr("r", 25) |
|
d3.select(this).transition().duration(100).attr("r", 30) |
|
}) |
|
.on("mouseleave", function(d) { |
|
node.transition().duration(100).attr("r", 25); |
|
}) |
|
|
|
gnodes.on("click", function(d,i) { |
|
swapPositions(d, d3.select(this)) |
|
}); |
|
|
|
var labels = gnodes.append("text") |
|
.attr("dy", 4) |
|
.text(function(d){return d.name}) |
|
|
|
|
|
function swapPositions(point, t) { |
|
|
|
simulation.on("tick", tick).alpha(0.1).restart() |
|
|
|
function tick() { |
|
|
|
d3.select(".centered").classed("centered", false) |
|
.transition().duration(100) |
|
.attr("transform", t.attr("transform")) |
|
|
|
d3.select(".node-" + point.id.toString()).classed("centered", true) |
|
.transition().duration(100) |
|
.attr("transform", "translate(" + width/2 + "," + height/2 + ")") |
|
|
|
// Uncomment to animate line |
|
//d3.select(".node-link-" + point.id.toString()).transition().duration(100) |
|
//.style('stroke', 'salmon') |
|
//.attr("d", function(d) { |
|
//var dx = d.target.x - d.source.x, |
|
//dy = d.target.y - d.source.y, |
|
//dr = Math.sqrt(dx * dx + dy * dy); |
|
//return "M" + |
|
//d.target.x + "," + |
|
//d.target.y + "A" + |
|
//dr + "," + dr + " 0 0,1 " + |
|
//d.source.x + "," + |
|
//d.source.y; |
|
//}); |
|
} |
|
|
|
} |
|
</script> |
|
</body> |
|
|
|
</html> |