Built with blockbuilder.org
Created
March 6, 2019 13:18
-
-
Save dianaow/8527233d67e2b72278388bd989eb5495 to your computer and use it in GitHub Desktop.
Evenly spaced nodes around center: Method 2
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
license: mit |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!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