Skip to content

Instantly share code, notes, and snippets.

@dianaow
Created March 6, 2019 13:18
Show Gist options
  • Save dianaow/8527233d67e2b72278388bd989eb5495 to your computer and use it in GitHub Desktop.
Save dianaow/8527233d67e2b72278388bd989eb5495 to your computer and use it in GitHub Desktop.
Evenly spaced nodes around center: Method 2
license: mit
<!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"},
{"id": 10,"name":"central"}
],
"links":[
{"id":1,"source":1,"target":10},
{"id":2,"source":2,"target":10},
{"id":3,"source":3,"target":10},
{"id":4,"source":4,"target":1},
{"id":5,"source":4,"target":9},
{"id":6,"source":5,"target":0},
{"id":7,"source":6,"target":5},
{"id":8,"source":7,"target":4},
{"id":9,"source":8,"target":0},
{"id":10,"source":9,"target":3}
]
};
var nodes = dataset.nodes
var links = dataset.links
createChart()
function createChart(error, csv, csv2, geoJSON){
// evenly spaces nodes along arc
var circleCoord = function(node, index, num_nodes){
var circumference = circle.node().getTotalLength();
var pointAtLength = function(l){return circle.node().getPointAtLength(l)};
var sectionLength = (circumference)/num_nodes;
var position = sectionLength*index+sectionLength/2;
return pointAtLength(circumference-position)
}
// fades out lines that aren't connected to node d
var is_connected = function(d, opacity) {
lines.transition().style("stroke-opacity", function(o) {
return o.source === d || o.target === d ? 1 : opacity;
});
}
// Initialize force simulation
simulation = d3.forceSimulation()
.force("link", d3.forceLink().id(function(d) { return d.id; }))
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);
// invisible circle for placing nodes
// it's actually two arcs so we can use the getPointAtLength() and getTotalLength() methods
var dim = width-80
var circle = svg.append("path")
.attr("d", "M 40, "+(dim/2+40)+" a "+dim/2+","+dim/2+" 0 1,0 "+dim+",0 a "+dim/2+","+dim/2+" 0 1,0 "+dim*-1+",0")
.style("fill", "white");
nodes.forEach(function(n, i) {
var coord = circleCoord(n, i, nodes.length-1)
n.x = coord.x
n.y = coord.y
});
// for straight line links
//var lines = svg.selectAll("line.node-link")
//.data(links).enter().append("line")
//.attr("class", function(d,i) { return "node-link node-link-"+ d.id.toString()})
//.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; });
// for curved links
var lines = svg.selectAll("path.node-link")
.data(links).enter().append("path")
.attr("class", function(d,i) { return "node-link node-link-"+ i.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-10").classed("centered", true)
.attr("transform", function(d,i) {
return "translate(" + width/2 + "," + height/2 + ")";
});
var toCenter = links.filter(d=>d.target.id==10).map(d=>d.id)
toCenter.map(point => {
d3.select(".node-link-" + (point-1).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 " +
width/2 + "," +
height/2;
});
})
var node = gnodes.append("circle")
.attr("r", 25)
.attr("class", "node")
.on("mouseenter", function(d) {
is_connected(d, 0.1)
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);
is_connected(d, 1);
})
.on("click", function(d,i) {
swapPositions(d)
});
var labels = gnodes.append("text")
.attr("dy", 4)
.text(function(d){return d.id})
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment