|
<!DOCTYPE html> |
|
<meta charset="utf-8"> |
|
<style> |
|
* { |
|
box-sizing: border-box; |
|
} |
|
html, |
|
body { |
|
margin: 0; |
|
padding: 0; |
|
width: 100%; |
|
height: 100%; |
|
} |
|
body { |
|
font-family: arial, sans-serif; |
|
background: radial-gradient(ellipse, #016cbe, #01266c), #016cbe; |
|
} |
|
|
|
.countries { |
|
position: absolute; |
|
top:0; |
|
left:0; |
|
} |
|
|
|
svg { |
|
position: absolute; |
|
top:0; |
|
left:0; |
|
overflow: visible; |
|
} |
|
|
|
.links line { |
|
stroke: #999; |
|
stroke-opacity: 0.75; |
|
stroke-width: .25; |
|
} |
|
|
|
</style> |
|
<link href="https://s3.amazonaws.com/stojkov.me/flags.css" type="text/css" rel="stylesheet"> |
|
<script src="https://d3js.org/d3.v4.min.js"></script> |
|
<script> |
|
function drawGraph(graph) { |
|
var body = d3.select("body"); |
|
var sizes = body.node().getBoundingClientRect(); |
|
var width = sizes.width; |
|
var height = sizes.height; |
|
|
|
var svg = body.append("svg") |
|
.attr("width", width) |
|
.attr("height", height); |
|
|
|
var countries = body.append("div") |
|
.style("width", width + "px") |
|
.style("height", height + "px"); |
|
|
|
var simulation = d3.forceSimulation() |
|
.force("link", d3.forceLink().id(function(d) { return d.index})) |
|
.force("charge", d3.forceManyBody().strength(-5)) |
|
.force("center", d3.forceCenter(width / 2, height / 2)); |
|
|
|
var link = svg.append("g") |
|
.attr("class", "links") |
|
.selectAll("line") |
|
.data(graph.links) |
|
.enter().append("line"); |
|
|
|
var node = countries.selectAll(".flag") |
|
.data(graph.nodes) |
|
.enter().append("span") |
|
.attr("class", function(d) { return "flag flag-" + d.code}) |
|
.attr("title", function(d) { return d.country}) |
|
.call(d3.drag() |
|
.on("start", dragstarted) |
|
.on("drag", dragged) |
|
.on("end", dragended)); |
|
|
|
simulation.nodes(graph.nodes).on("tick", ticked); |
|
simulation.force("link").links(graph.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.style("transform", function(d) { return "translate3d(" + d.x + "px, " + d.y + "px, 0) scale(.5, .5)"}); |
|
} |
|
|
|
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; |
|
} |
|
} |
|
|
|
d3.json("https://raw.githubusercontent.com/DealPete/forceDirected/master/countries.json", function(err, data) { |
|
if(err) throw err; |
|
|
|
drawGraph(data); |
|
}); |
|
</script> |