|
<!DOCTYPE html> |
|
<meta charset="utf-8"> |
|
<style> |
|
|
|
body { |
|
font-family: sans-serif; |
|
margin: auto; |
|
position: relative; |
|
width: 600px; |
|
} |
|
.controls { |
|
left: 50%; |
|
position: absolute; |
|
top: 2em; |
|
transform: translateX(-50%); |
|
} |
|
.blob { |
|
stroke: #fff; |
|
stroke-width: 1.5px; |
|
} |
|
.text { |
|
fill: #fff; |
|
font-size: 0.8125em; |
|
text-anchor: middle; |
|
} |
|
.link { |
|
stroke: #433; |
|
} |
|
|
|
</style> |
|
<body> |
|
<div class="controls"> |
|
<label><input type="checkbox" id="rearrange"> Use left-to-right arrangement</label> |
|
</div> |
|
<script src="//d3js.org/d3.v3.js"></script> |
|
<!--<script src="/ausvoteflow/frontbench/d3.js"></script>--> |
|
<script> |
|
|
|
var width = 600, |
|
height = 600, |
|
nodeRadius = 15, |
|
nodeCount = 23, |
|
circleRadius = height / 3; |
|
|
|
var cx = width / 2, |
|
cy = height / 2, |
|
shouldRearrange = false; |
|
|
|
var svg = d3.select('body').append('svg') |
|
.attr('width', width) |
|
.attr('height', height) |
|
.append('g') |
|
.attr('transform', 'translate(' + [cx, cy] + ')'); |
|
|
|
var nodes = d3.range(nodeCount).map(function (n) { |
|
return { |
|
num: n, |
|
hue: n / nodeCount * 300 |
|
}; |
|
}); |
|
|
|
var links = d3.range(nodeCount - 1).map(function (n) { |
|
return { |
|
from: nodes[n], |
|
to: nodes[n + 1] |
|
}; |
|
}); |
|
|
|
var angleRads = Math.PI * 2 / nodeCount; |
|
|
|
var links = svg.selectAll('.link') |
|
.data(links) |
|
.enter().append('line') |
|
.attr({ |
|
'class': 'link', |
|
x1: 0, |
|
y1: 0, |
|
x2: 0, |
|
y2: 0 |
|
}); |
|
|
|
var blobs = svg.selectAll('.node') |
|
.data(nodes, function (d) { return d.num; }) |
|
.enter().append('g') |
|
.attr('class', 'node'); |
|
|
|
blobs.append('circle') |
|
.attr('class', 'blob') |
|
.attr('r', nodeRadius) |
|
.attr('fill', function (d) { return 'hsl(' + d.hue + ', 50%, 50%)'; }); |
|
|
|
blobs.append('text') |
|
.attr('class', 'text') |
|
.attr('dy', '0.35em') |
|
.text(function (d) { return d.num + 1; }); |
|
|
|
function render() { |
|
var nodeData = shouldRearrange ? rearrange(nodes) : nodes; |
|
|
|
d3.transition() |
|
.duration(1000) |
|
.each(function () { |
|
blobs |
|
.data(nodeData, function (d) { return d.num; }) |
|
.transition() |
|
.attr('transform', function (d, i) { |
|
var angle = angleRads * i - Math.PI / 2; |
|
d.x = Math.sin(angle) * circleRadius; |
|
d.y = Math.cos(angle) * circleRadius; |
|
return 'translate(' + [d.x, d.y] + ')'; |
|
}); |
|
|
|
links |
|
.transition() |
|
.attr({ |
|
x1: function (d) { return d.from.x; }, |
|
y1: function (d) { return d.from.y; }, |
|
x2: function (d) { return d.to.x; }, |
|
y2: function (d) { return d.to.y; } |
|
}); |
|
}); |
|
} |
|
|
|
// [1, 2, 3, 4, 5, 6, 7] => [1, 3, 5, 7, 6, 4, 2] |
|
function rearrange(nodes) { |
|
var left = [], right = []; |
|
nodes.forEach(function (node, i) { |
|
(i % 2 ? right : left).push(node); |
|
}); |
|
return left.concat(right.reverse()); |
|
} |
|
|
|
document.getElementById('rearrange').addEventListener('change', function () { |
|
shouldRearrange = this.checked; |
|
render(); |
|
}, false); |
|
|
|
render(); |
|
|
|
</script> |