xxxxxxxxxx
<script src="https://d3js.org/d3.v3.min.js"></script>
<p id="chart">
<script>
// set margins, size
var margin = {top: 0, right: 0, bottom: 0, left: 0},
width = 1040 - margin.left - margin.right,
height = 620 - margin.top - margin.bottom;
// append the svg canvas to the page
var svg = d3.select("#chart").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform",
"translate(" + margin.left + "," + margin.top + ")");
// set up scales
var x = d3.scale.linear()
.domain([-260,260])
.range([0, width])
var y = d3.scale.linear()
.domain([-145, 165])
.range([height, 0])
var r = d3.scale.linear()
.domain([0,50])
.range([0,100])
d3.csv("centroids.csv", function (error, data) {
data.forEach(function(d) {
d.x = parseFloat(d.x);
d.y = parseFloat(d.y);
d.x_original = d.x;
d.y_original = d.y;
d.x_next = d.x;
d.y_next = d.y;
d.r = 20;
})
var circles = svg.selectAll(".circle")
.data(data)
.enter()
.append("circle")
.attr("cx", function(d) {
return x(d.x)
})
.attr("cy", function(d) {
return y(d.y)
})
.attr("r", function(d) {
return r(d.r*.8)
})
.attr("fill", function(d) {
return d.color
})
.attr("stroke",function(d) {
return "#000"
})
.attr("stroke-width",function(d) {
if (d.region == 'Praha' || d.region == 'Brno' || d.region == 'Ostrava' || d.region == 'Plze')
return 10
else
return 2
})
.attr("fill-opacity",function(d, i) {
return .5
})
.attr("title", function(d) {
return d.name + ": " + d.senator
})
function distance(d1, d2){
return Math.sqrt((d1.x-d2.x)*(d1.x-d2.x) + (d1.y-d2.y)*(d1.y-d2.y))
}
function unitvector(d1, d2) {
var distx = d1.x - d2.x;
var disty = d1.y - d2.y;
var size = Math.sqrt(distx*distx + disty*disty);
if (size > 0) {
return [distx/size, disty/size]
} else {
return [0, 0]
}
}
function repulsive(d1, d2, a=0.05) {
var gap = distance(d1, d2) - d1.r - d2.r;
if (gap < 0) {
var unitv = unitvector(d1, d2);
return {'dx': -1*unitv[0]*gap*a, 'dy': -1*unitv[1]*gap*a }
} else {
return {'dx': 0, 'dy': 0}
}
}
function attractive(d, b=0.1) {
var orig = {'x': d.x_original, 'y': d.y_original}
var dist = distance(d, orig);
var unitv = unitvector(d, orig);
return {'dx': -1*unitv[0]*dist*b, 'dy': -1*unitv[1]*dist*b }
}
conflicted = []
for (k=0; k<1000; k++) {
for (var i=0; i<data.length; i++) {
data[i].x_next = data[i].x;
data[i].y_next = data[i].y;
}
for (var i=0; i<data.length; i++) {
conflicted[i] = false;
for (var j=i+1; j<data.length; j++) {
repuls = repulsive(data[i], data[j])
data[i]['x_next'] += repuls['dx'];
data[i]['y_next'] += repuls['dy'];
data[j]['x_next'] += -1*repuls['dx'];
data[j]['y_next'] += -1*repuls['dy'];
if (repuls['dx'] != 0 || repuls['dy'] != 0) {
conflicted[i] = true;
conflicted[j] = true;
}
}
}
for (var i=0; i<data.length; i++) {
if (conflicted[i]) {
attract = attractive(data[i], 0.01);
} else {
attract = attractive(data[i])
}
data[i]['x_next'] += attract['dx'];
data[i]['y_next'] += attract['dy'];
}
for (var i=0; i<data.length; i++) {
data[i].x = data[i].x_next;
data[i].y = data[i].y_next;
}
d3.selectAll("circle")
.transition()
.duration(100)
.delay(function() {
return k * 50
})
.attr("cx", function(d) {
return x(d.x)
})
.attr("cy", function(d) {
return y(d.y)
})
}
nothing = 0
})
</script>
Modified http://d3js.org/d3.v3.min.js to a secure url
https://d3js.org/d3.v3.min.js