index.html
<!DOCTYPE html>
<html>
<head>
<title>Regional elections 2013, Banská Bystrica, Chairman - 2nd round</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="initial-scale=1.0, user-scalable=no"/>
<script src="//code.jquery.com/jquery-1.8.2.min.js"></script>
<script>
</script>
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.2/css/bootstrap.min.css">
<link rel="stylesheet" href="//cdn.leafletjs.com/leaflet-0.6.4/leaflet.css" />
<script src="//cdn.leafletjs.com/leaflet-0.6.4/leaflet.js"></script>
<script type="text/javascript" src="//mbostock.github.com/d3/d3.js?1.29.1"></script>
<style type="text/css">
html, body, #map {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
svg:not(:root) {
overflow: visible;
}
circle {
fill: #888;
fill-opacity: 0.01;
stroke-opacity: 0.75;
cursor:pointer;
}
.marian-kotleba {
stroke: #040;
color: #080;
fill: #040;
}
.vladimir-manka {
stroke: #f00;
color: #f00;
fill: #f00;
}
div.tooltip
{
position: absolute;
text-align: center;
width: 140px;
padding: 8px;
font: 10px sans-serif;
background: #ffff99;
border: solid 1px #aaa;
border-radius: 8px;
pointer-events: none;
}
</style>
</head>
<body>
<div class="navbar navbar-inverse navbar-fixed-top" role="navigation">
<div class="container">
<div class="navbar-header">
<a class="navbar-brand" href="#">Regional elections 2013, Banská Bystrica, Chairman - 2nd round - <span class="marian-kotleba">Kotleba</span> vs. <span class="vladimir-manka">Maňka</span></a>
</div>
</div>
</div>
<div style="position:fixed;top:50px;z-index:1000;">
<div class="alert alert-info">The <strong>size</strong> of bubbles represents number of voters, the <strong>color</strong> represents the winner and the <strong>width of rings</strong> the margin of victory.</div>
<div class="alert alert-danger alert-dismissable">As of 2013-12-02: works ok on last <strong>Firefox</strong>, does not work on <strong>Opera</strong> and <strong>Chrome/Chromium</strong><br/>
2014-07-02: solution shown in map.html
</div>
</div>
<div id="map" style="margin-top:40px;"></div>
<script type="text/javascript">
var map = L.map('map',{zoomControl: false}).setView([48.565703,19.390411], 9);
map.addControl( L.control.zoom({position: 'topright'}) );
L.tileLayer('//{s}.www.toolserver.org/tiles/bw-mapnik/{z}/{x}/{y}.png', {
attribution: '© <a href="//osm.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map);
var svg = d3.select(map.getPanes().overlayPane).append("div").attr("class", "stations"),
g = svg.append("g").attr("class", "leaflet-zoom-hide");
var radiusScale = d3.scale.sqrt().domain([0, 50000]).range([0, 100]);
var div = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 1e-6);
d3.json( "sk_vuc_2013_2_ring_marian-kotleba_vladimir-manka.json", function (data) {
nodes = data.features
.map(function(d) {
mpoint = projectPoint(d.coordinates[0],d.coordinates[1]);
perc1 = Math.round(Math.max(parseInt(d.population.p6),parseInt(d.population.p9)) / (parseInt(d.population.p6)+parseInt(d.population.p9)) * 100);
perc2 = 100 - perc1;
return {
x: mpoint.x,
y: mpoint.y,
r: (radiusScale(d.population.p6)+radiusScale(d.population.p9))/2* Math.pow(map.getZoom(),3) / 729,
r2: Math.abs(radiusScale(d.population.p9)-radiusScale(d.population.p6))* Math.pow(map.getZoom(),3) / 729,
name: d.name,
classname: d.classname,
title: d.name + ': ' + d.winner + ' vyhral ' + perc1 + " % vs. " + perc2 + " % ("+ Math.max(d.population.p6,d.population.p9) + ':' + Math.min(d.population.p6,d.population.p9) + " hlasov)",
value: d
};
});
var node = svg.selectAll("svg")
.data(nodes)
.enter().append("svg:svg").append("svg:circle")
.attr("cx", function (d) {return d.x})
.attr("cy", function (d) {return d.y})
.attr("r", function (d) {return d.r})
.attr("stroke-width", function(d) {return d.r2})
.attr("class", function(d) {return d.classname})
.on("mouseover", mouseover)
.on("mousemove", function(d){mousemove(d);})
.on("mouseout", mouseout);
});
function class2color(className) {
if (className == 'marian-kotleba') return "#040";
else return "#f00";
}
function projectPoint(x, y) {
var point = map.latLngToLayerPoint(new L.LatLng(y, x));
return point;
}
function mouseover() {
div.transition()
.duration(300)
.style("opacity", 1);
}
function mousemove(d) {
div
.text(d.title)
.style("left", (d3.event.pageX ) + "px")
.style("top", (d3.event.pageY) + "px");
}
function mouseout() {
div.transition()
.duration(300)
.style("opacity", 1e-6);
}
map.on("zoomend", zoomit);
function zoomit() {
d3.selectAll("circle").each(function(d,i) {
mpoint = projectPoint(d.value.coordinates[0],d.value.coordinates[1]);
$(this)
.attr("r",
(radiusScale(d.value.population.p6)+radiusScale(d.value.population.p9))/2 * Math.pow(map.getZoom(),3) / 729
)
.attr("stroke-width",
Math.abs(radiusScale(d.value.population.p9)-radiusScale(d.value.population.p6)) * Math.pow(map.getZoom(),3) / 729
)
.attr("cx", mpoint.x)
.attr("cy", mpoint.y);
})
}
</script>
</body>
</html>
map.html
<!DOCTYPE html>
<html>
<head>
<title>Banská Bystrica (region 2013)</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="initial-scale=1.0, user-scalable=no"/>
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootswatch/3.2.0/cerulean/bootstrap.min.css">
<link rel="stylesheet" href="//cdn.leafletjs.com/leaflet-0.7.3/leaflet.css" />
<script src="//cdn.leafletjs.com/leaflet-0.7.3/leaflet.js"></script>
<script src="//d3js.org/d3.v3.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
<style type="text/css">
.leaflet-tile-pane {
opacity: .4
}
.leaflet-container {
background-color: #fff;
}
html, body{
width: 100%;
height: 100%;
}
#map {
width: 100%;
height: 90%;
}
circle {
color: #080;
fill: #040;
stroke: #040;
cursor: pointer;
fill: #888;
fill-opacity: 0.01;
stroke-opacity: 0.75;
}
svg {
width: 100000px;
height: 100000px;
}
svg:not(:root) {
overflow: visible;
}
</style>
</head>
<body>
<div id="map"></div>
<div class="btn-group" data-toggle="buttons" id="buttons0"></div>
<div class="btn-group" data-toggle="buttons" id="buttons1"></div>
<div class="btn-group" data-toggle="buttons" id="buttons2"></div>
<script type="text/javascript">
var vars = {population: 'voters', ns: ['Maňka','Kotleba'], name: 'name'};
var map = L.map('map').setView([48.565703,19.390411], 9);
L.tileLayer('//{s}.www.toolserver.org/tiles/bw-mapnik/{z}/{x}/{y}.png', {
attribution: 'CC-BY Michal Škop | © <a href="//osm.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map);
var svg = d3.select(map.getPanes().overlayPane).append("div").attr("class", "towns");
var radiusScale = d3.scale.sqrt().domain([0, 50000]).range([0, 100]);
d3.csv('data.csv', function(data) {
var keys0 = Object.keys(data[0]);
var keys = [];
for (var k in keys0) {
key = keys0[k];
if (!((['id','lat','lon'].indexOf(key) > -1) || isNaN(parseFloat(data[1][key])))) {
keys.push(key);
}
}
addButtons(keys,'buttons0','info');
addButtons(keys,'buttons1','success');
addButtons(keys,'buttons2','warning');
nodes = data
.map(function(d) {
mpoint = projectPoint(d.lat,d.lon);
return {
x: mpoint.x,
y: mpoint.y,
r: radiusScale(d[vars['population']]),
name: d[vars['name']],
value: d
};
});
var circle = svg.selectAll("svg")
.data(nodes)
.enter().append("svg:svg")
.append("svg:circle")
.attr("cx", function (d) {return d.x})
.attr("cy", function (d) {return d.y})
.attr("r", function (d) {return d.r});
function projectPoint(x, y) {
var point = map.latLngToLayerPoint(new L.LatLng(x, y));
return point;
}
function matrixVal(s) {
return s.split('(')[1].split(')')[0].split(',');
}
map.on("viewreset", changeit);
map.on("moveend", changeit);
function changeit() {
var s = $(".leaflet-map-pane").css("-webkit-transform");
if (typeof(s) == 'undefined')
var s = $(".leaflet-map-pane").css("transform");
var sar = matrixVal(s);
d3.selectAll("circle").each(function(d,i) {
mpoint = projectPoint(d.value.lat,d.value.lon);
$(this)
.attr("r",
radiusScale(d.value[vars['population']]) * Math.pow(map.getZoom(),3) / 729
)
.attr("cx", mpoint.x)
.attr("cy", mpoint.y);
$(this).attr('transform',"translate(" + sar[4] + "," + sar[5] + ")");
$(this).parent().css('left',-1*parseFloat(sar[4]));
$(this).parent().css('top',-1*parseFloat(sar[5]));
});
}
});
function addButtons(keys,id,btype) {
for (k in keys) {
key = keys[k];
$("#"+id).append('<label class="btn btn-'+btype+'"><input type="radio" name="options" id="option-'+k+'">'+key+'</label>');
}
$('.btn').button();
}
</script>
</body>
</html>