index.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>
<script src="d3.tip.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: 70%;
}
circle {
cursor: pointer;
fill-opacity: 0.8;
stroke-opacity: 0.75;
}
svg {
width: 100000px;
height: 100000px;
}
svg:not(:root) {
overflow: visible;
}
.d3-tip {
line-height: 1;
font-weight: bold;
padding: 12px;
background: rgba(0, 0, 0, 0.8);
color: #fff;
border-radius: 2px;
}
.d3-tip.n:after {
margin: -1px 0 0 0;
top: 100%;
left: 0;
}
.stronger {
color: yellow;
}
.navbar {
margin-bottom: 0;
}
</style>
</head>
<body>
<div class="navbar navbar-default">
<div class="navbar-header">
<a class="navbar-brand">Banská Bystrica region, 2013</a>
</div>
</div>
<div style="position:fixed;top:52px;z-index:1000;">
<div class="alert alert-info" >Results by electoral districts.</div>
</div>
<div id="map"></div>
<div class="form-group">
<label for="select-size-wrap" class="col-sm-1 control-label">Size</label>
<div id="select-size-wrap" class="col-sm-11">
<select id="select-size" class="form-control switch">
</select>
</div>
</div>
<div class="form-group">
<label for="select-plus-wrap" class="col-sm-1 control-label">Green</label>
<div id="select-plus-wrap" class="col-sm-11">
<select id="select-plus" class="form-control switch">
</select>
</div>
</div>
<div class="form-group">
<label for="select-minus-wrap" class="col-sm-1 control-label">Red</label>
<div id="select-minus-wrap" class="col-sm-11">
<select id="select-minus" class="form-control switch">
</select>
</div>
</div>
<script type="text/javascript">
var vars = {population: 'voted2', ns: ['Maňka2','Kotleba2'], name: 'name'};
var map = L.map('map', {'zoomControl':false}).setView([48.6500,19.1499], 11);
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);
L.control.zoom({"position":"topright"}).addTo(map);
var svg = d3.select(map.getPanes().overlayPane).append("svg").attr("class", "towns");
var radiusScale = d3.scale.sqrt().domain([0, 25000]).range([0, 50]);
var keys = [];
var color = colorscale([0,0.5,1],["red", "yellow", "green"]);
var tip = changetooltip();
svg.call(tip);
var div = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 1e-6);
d3.csv('data2.csv', function(data) {
var keys0 = Object.keys(data[0]);
for (var k in keys0) {
key = keys0[k];
if (!((['id','lat','lon'].indexOf(key) > -1) || isNaN(parseFloat(data[1][key])))) {
keys.push(key);
}
}
addSelects(keys,'size',0);
addSelects(keys,'plus',1);
addSelects(keys,'minus',2);
$(".switch").on("change",function() {
changeitems(name2id(this.id),name2id($(this).children(":selected").attr("id")));
});
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})
.attr("fill", function(d) {
one = parseFloat(d.value[vars['ns'][0]]);
two = parseFloat(d.value[vars['ns'][1]]);
return color(two/(one+two));
})
.on("mouseover", tip.show)
.on("mouseout", tip.hide);
map.on("viewreset", changeit);
map.on("moveend", changeit);
map.on("zoomstart", hidepoints);
$(".towns").show(100);
});
function hidepoints() {
$(".towns").hide();
}
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(',');
}
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);
$(".towns").css('left',-1*parseFloat(sar[4]));
$(".towns").css('top',-1*parseFloat(sar[5]));
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] + ")");
});
$(".towns").show(300);
}
function changeitems(change, id) {
if (change == 'size') {
vars['population'] = keys[id];
changesize();
}
if (change == 'plus') {
vars['ns'][1] = keys[id];
changecolor();
}
if (change == 'minus') {
vars['ns'][0] = keys[id];
changecolor();
}
}
function changecolor() {
domain = [0,0.5,1];
range = ["red", "yellow", "green"];
color = colorscale(domain,range);
d3.selectAll("circle").each(function(data,i) {
d3.select(this)
.attr("stroke-width", 30)
.attr("fill", function(d) {
one = parseFloat(d.value[vars['ns'][0]]);
two = parseFloat(d.value[vars['ns'][1]]);
return color(two/(one+two));
})
});
}
function changesize() {
d3.selectAll("circle").each(function(data,i) {
d3.select(this)
.transition()
.delay(0)
.duration(300)
.attr("r",
radiusScale(data.value[vars['population']]) * Math.pow(map.getZoom(),3) / 729
)
});
}
function changetooltip() {
tip = d3.tip().attr('class', 'd3-tip').html(function(d) {
html = '<span class="stronger">' + d.value[vars['name']] + "</span><br>";
html += vars['population'] + ': ' + d.value[vars['population']] + '<br>';
html += vars['ns'][1] + ': ' + d.value[vars['ns'][1]] + '<br>';
html += vars['ns'][0] + ': ' + d.value[vars['ns'][0]] + '<br>';
return html;
});
return tip;
}
function colorscale(domain,range) {
return d3.scale.linear()
.domain(domain)
.range(range);
}
function name2id(n) {
ar = n.split("-");
ar.splice(0,1);
return ar.join('-');
}
function addSelects(keys,id,selected) {
for (k in keys) {
key = keys[k];
if (selected == k) sel = 'selected'; else sel = '';
$("#select-"+id).append('<option id="option-'+k+'" '+sel+' class="switch">'+key+'</option>');
}
}
</script>
</body>
</html>
d3.tip.js
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
define(['d3'], factory)
} else {
root.d3.tip = factory(root.d3)
}
}(this, function (d3) {
return function() {
var direction = d3_tip_direction,
offset = d3_tip_offset,
html = d3_tip_html,
node = initNode(),
svg = null,
point = null,
target = null
function tip(vis) {
svg = getSVGNode(vis)
point = svg.createSVGPoint()
document.body.appendChild(node)
}
tip.show = function() {
var args = Array.prototype.slice.call(arguments)
if(args[args.length - 1] instanceof SVGElement) target = args.pop()
var content = html.apply(this, args),
poffset = offset.apply(this, args),
dir = direction.apply(this, args),
nodel = d3.select(node),
i = directions.length,
coords,
scrollTop = document.documentElement.scrollTop || document.body.scrollTop,
scrollLeft = document.documentElement.scrollLeft || document.body.scrollLeft
nodel.html(content)
.style({ opacity: 1, 'pointer-events': 'all' })
while(i--) nodel.classed(directions[i], false)
coords = direction_callbacks.get(dir).apply(this)
nodel.classed(dir, true).style({
top: (coords.top + poffset[0]) + scrollTop + 'px',
left: (coords.left + poffset[1]) + scrollLeft + 'px'
})
return tip
}
tip.hide = function() {
nodel = d3.select(node)
nodel.style({ opacity: 0, 'pointer-events': 'none' })
return tip
}
tip.attr = function(n, v) {
if (arguments.length < 2 && typeof n === 'string') {
return d3.select(node).attr(n)
} else {
var args = Array.prototype.slice.call(arguments)
d3.selection.prototype.attr.apply(d3.select(node), args)
}
return tip
}
tip.style = function(n, v) {
if (arguments.length < 2 && typeof n === 'string') {
return d3.select(node).style(n)
} else {
var args = Array.prototype.slice.call(arguments)
d3.selection.prototype.style.apply(d3.select(node), args)
}
return tip
}
tip.direction = function(v) {
if (!arguments.length) return direction
direction = v == null ? v : d3.functor(v)
return tip
}
tip.offset = function(v) {
if (!arguments.length) return offset
offset = v == null ? v : d3.functor(v)
return tip
}
tip.html = function(v) {
if (!arguments.length) return html
html = v == null ? v : d3.functor(v)
return tip
}
function d3_tip_direction() { return 'n' }
function d3_tip_offset() { return [0, 0] }
function d3_tip_html() { return ' ' }
var direction_callbacks = d3.map({
n: direction_n,
s: direction_s,
e: direction_e,
w: direction_w,
nw: direction_nw,
ne: direction_ne,
sw: direction_sw,
se: direction_se
}),
directions = direction_callbacks.keys()
function direction_n() {
var bbox = getScreenBBox()
return {
top: bbox.n.y - node.offsetHeight,
left: bbox.n.x - node.offsetWidth / 2
}
}
function direction_s() {
var bbox = getScreenBBox()
return {
top: bbox.s.y,
left: bbox.s.x - node.offsetWidth / 2
}
}
function direction_e() {
var bbox = getScreenBBox()
return {
top: bbox.e.y - node.offsetHeight / 2,
left: bbox.e.x
}
}
function direction_w() {
var bbox = getScreenBBox()
return {
top: bbox.w.y - node.offsetHeight / 2,
left: bbox.w.x - node.offsetWidth
}
}
function direction_nw() {
var bbox = getScreenBBox()
return {
top: bbox.nw.y - node.offsetHeight,
left: bbox.nw.x - node.offsetWidth
}
}
function direction_ne() {
var bbox = getScreenBBox()
return {
top: bbox.ne.y - node.offsetHeight,
left: bbox.ne.x
}
}
function direction_sw() {
var bbox = getScreenBBox()
return {
top: bbox.sw.y,
left: bbox.sw.x - node.offsetWidth
}
}
function direction_se() {
var bbox = getScreenBBox()
return {
top: bbox.se.y,
left: bbox.e.x
}
}
function initNode() {
var node = d3.select(document.createElement('div'))
node.style({
position: 'absolute',
top: 0,
opacity: 0,
'pointer-events': 'none',
'box-sizing': 'border-box'
})
return node.node()
}
function getSVGNode(el) {
el = el.node()
if(el.tagName.toLowerCase() == 'svg')
return el
return el.ownerSVGElement
}
function getScreenBBox() {
var targetel = target || d3.event.target,
bbox = {},
matrix = targetel.getScreenCTM(),
tbbox = targetel.getBBox(),
width = tbbox.width,
height = tbbox.height,
x = tbbox.x,
y = tbbox.y
point.x = x
point.y = y
bbox.nw = point.matrixTransform(matrix)
point.x += width
bbox.ne = point.matrixTransform(matrix)
point.y += height
bbox.se = point.matrixTransform(matrix)
point.x -= width
bbox.sw = point.matrixTransform(matrix)
point.y -= height / 2
bbox.w = point.matrixTransform(matrix)
point.x += width
bbox.e = point.matrixTransform(matrix)
point.x -= width / 2
point.y -= height / 2
bbox.n = point.matrixTransform(matrix)
point.y += height
bbox.s = point.matrixTransform(matrix)
return bbox
}
return tip
};
}));
geocode.py
import csv
import requests
import json
outfile = open('geocoded.csv', 'wt')
outwriter = csv.writer(outfile, quoting=csv.QUOTE_NONNUMERIC)
dReader = csv.reader(open('okrsky.tsv'),delimiter="\t")
for row in dReader:
if i > 0:
sfields = row[6].split(',')
lat = 0
lon = 0
k = 0
for item in sfields:
sli = item.split('-')
j = 0
for street in sli:
if j == 0:
sbits = street.strip().split(' ')
sbits.pop()
juststreet = sbits.join(' ')
else:
street = juststreet + ' ' + street
j = j + 1
url = "http://nominatim.openstreetmap.org/search?country=Slovakia&format=json&accept-language=sk&city=" + row[2].strip() + "street=" + street
r = requests.get(url)
djson = json.loads(r.text)
if len(djson) > 0:
k = k + 1
lat = lat + djson[0]['lat']
lon = lon + djson[0]['lon']
orow = row
if k > 0:
lat = lat / k
lon = lon / k
orow = orow + [lat,lon]
outwriter.writerow(orow)
raise(Exception,'')
outfile.close()
index2.html
<!DOCTYPE html>
<html>
<head>
<title>Banská Bystrica (region 2013, EP 2014)</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>
<script src="d3.tip.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: 70%;
}
circle {
cursor: pointer;
fill-opacity: 0.8;
stroke-opacity: 0.75;
}
svg {
width: 100000px;
height: 100000px;
}
svg:not(:root) {
overflow: visible;
}
.d3-tip {
line-height: 1;
font-weight: bold;
padding: 12px;
background: rgba(0, 0, 0, 0.8);
color: #fff;
border-radius: 2px;
}
.d3-tip.n:after {
margin: -1px 0 0 0;
top: 100%;
left: 0;
}
.stronger {
color: yellow;
}
.navbar {
margin-bottom: 0;
}
</style>
</head>
<body>
<div class="navbar navbar-default">
<div class="navbar-header">
<a class="navbar-brand">Banská Bystrica regional elestions 2013, EP 2014</a>
</div>
</div>
<div style="position:fixed;top:52px;z-index:1000;">
<div class="alert alert-info" >Results by towns.</div>
</div>
<div id="map"></div>
<div class="form-group">
<label for="select-size-wrap" class="col-sm-1 control-label">Size</label>
<div id="select-size-wrap" class="col-sm-11">
<select id="select-size" class="form-control switch">
</select>
</div>
</div>
<div class="form-group">
<label for="select-plus-wrap" class="col-sm-1 control-label">Green</label>
<div id="select-plus-wrap" class="col-sm-11">
<select id="select-plus" class="form-control switch">
</select>
</div>
</div>
<div class="form-group">
<label for="select-minus-wrap" class="col-sm-1 control-label">Red</label>
<div id="select-minus-wrap" class="col-sm-11">
<select id="select-minus" class="form-control switch">
</select>
</div>
</div>
<script type="text/javascript">
var vars = {population: 'VUC2013:voted-2ndround', ns: ['VUC2013:Maňka2=2ndround','VUC2013:Kotleba-2ndround'], name: 'name'};
var map = L.map('map', {'zoomControl':false}).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);
L.control.zoom({"position":"topright"}).addTo(map);
var svg = d3.select(map.getPanes().overlayPane).append("svg").attr("class", "towns");
var radiusScale = d3.scale.sqrt().domain([0, 50000]).range([0, 100]);
var keys = [];
var color = colorscale([0,0.5,1],["red", "yellow", "green"]);
var tip = changetooltip();
svg.call(tip);
var div = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 1e-6);
d3.csv('data3.csv', function(data) {
var keys0 = Object.keys(data[0]);
for (var k in keys0) {
key = keys0[k];
if (!((['id','lat','lon'].indexOf(key) > -1) || isNaN(parseFloat(data[1][key])))) {
keys.push(key);
}
}
addSelects(keys,'size',0);
addSelects(keys,'plus',1);
addSelects(keys,'minus',2);
$(".switch").on("change",function() {
changeitems(name2id(this.id),name2id($(this).children(":selected").attr("id")));
});
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})
.attr("fill", function(d) {
one = parseFloat(d.value[vars['ns'][0]]);
two = parseFloat(d.value[vars['ns'][1]]);
return color(two/(one+two));
})
.on("mouseover", tip.show)
.on("mouseout", tip.hide);
map.on("viewreset", changeit);
map.on("moveend", changeit);
map.on("zoomstart", hidepoints);
$(".towns").show(100);
});
function hidepoints() {
$(".towns").hide();
}
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(',');
}
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);
$(".towns").css('left',-1*parseFloat(sar[4]));
$(".towns").css('top',-1*parseFloat(sar[5]));
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] + ")");
});
$(".towns").show(300);
}
function changeitems(change, id) {
if (change == 'size') {
vars['population'] = keys[id];
changesize();
}
if (change == 'plus') {
vars['ns'][1] = keys[id];
changecolor();
}
if (change == 'minus') {
vars['ns'][0] = keys[id];
changecolor();
}
}
function changecolor() {
domain = [0,0.5,1];
range = ["red", "yellow", "green"];
color = colorscale(domain,range);
d3.selectAll("circle").each(function(data,i) {
d3.select(this)
.attr("stroke-width", 30)
.attr("fill", function(d) {
one = parseFloat(d.value[vars['ns'][0]]);
two = parseFloat(d.value[vars['ns'][1]]);
return color(two/(one+two));
})
});
}
function changesize() {
d3.selectAll("circle").each(function(data,i) {
d3.select(this)
.transition()
.delay(0)
.duration(300)
.attr("r",
radiusScale(data.value[vars['population']]) * Math.pow(map.getZoom(),3) / 729
)
});
}
function changetooltip() {
tip = d3.tip().attr('class', 'd3-tip').html(function(d) {
html = '<span class="stronger">' + d.value[vars['name']] + "</span><br>";
html += vars['population'] + ': ' + d.value[vars['population']] + '<br>';
html += vars['ns'][1] + ': ' + d.value[vars['ns'][1]] + '<br>';
html += vars['ns'][0] + ': ' + d.value[vars['ns'][0]] + '<br>';
return html;
});
return tip;
}
function colorscale(domain,range) {
return d3.scale.linear()
.domain(domain)
.range(range);
}
function name2id(n) {
ar = n.split("-");
ar.splice(0,1);
return ar.join('-');
}
function addSelects(keys,id,selected) {
for (k in keys) {
key = keys[k];
if (selected == k) sel = 'selected'; else sel = '';
$("#select-"+id).append('<option id="option-'+k+'" '+sel+' class="switch">'+key+'</option>');
}
}
</script>
</body>
</html>
index_older.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>
<script src="d3.tip.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: 80%;
}
circle {
cursor: pointer;
fill-opacity: 0.8;
stroke-opacity: 0.75;
}
svg {
width: 100000px;
height: 100000px;
}
svg:not(:root) {
overflow: visible;
}
.d3-tip {
line-height: 1;
font-weight: bold;
padding: 12px;
background: rgba(0, 0, 0, 0.8);
color: #fff;
border-radius: 2px;
}
.d3-tip.n:after {
margin: -1px 0 0 0;
top: 100%;
left: 0;
}
.stronger {
color: yellow;
}
</style>
</head>
<body>
<div id="map"></div>
<div>Size: <div class="btn-group btn-group-xs" data-toggle="buttons" id="buttons-size"></div></div>
<div>Plus: <div class="btn-group btn-group-xs" data-toggle="buttons" id="buttons-plus"></div></div>
<div>Minus: <div class="btn-group btn-group-xs" data-toggle="buttons" id="buttons-minus"></div></div>
<script type="text/javascript">
var vars = {population: 'voted2', ns: ['Maňka2','Kotleba2'], 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("svg").attr("class", "towns");
var radiusScale = d3.scale.sqrt().domain([0, 50000]).range([0, 100]);
var keys = [];
var color = colorscale([0,0.5,1],["green", "yellow", "red"]);
var tip = changetooltip();
svg.call(tip);
var div = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 1e-6);
d3.csv('data.csv', function(data) {
var keys0 = Object.keys(data[0]);
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,'size','info');
addButtons(keys,'plus','success');
addButtons(keys,'minus','danger');
$(".switch").on("change",function() {
changeitems(name2id(this.name),name2id(this.id))
});
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})
.attr("fill", function(d) {
one = parseFloat(d.value[vars['ns'][0]]);
two = parseFloat(d.value[vars['ns'][1]]);
return color(two/(one+two));
})
.on("mouseover", tip.show)
.on("mouseout", tip.hide);
map.on("viewreset", changeit);
map.on("moveend", changeit);
map.on("zoomstart", hidepoints);
$(".towns").show(100);
});
function hidepoints() {
$(".towns").hide();
}
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(',');
}
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);
$(".towns").css('left',-1*parseFloat(sar[4]));
$(".towns").css('top',-1*parseFloat(sar[5]));
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] + ")");
});
$(".towns").show(300);
}
function changeitems(change, id) {
if (change == 'size') {
vars['population'] = keys[id];
changesize();
}
if (change == 'plus') {
vars['ns'][1] = keys[id];
changecolor();
}
if (change == 'minus') {
vars['ns'][0] = keys[id];
changecolor();
}
}
function changecolor() {
domain = [0,0.5,1];
range = ["red", "yellow", "green"];
color = colorscale(domain,range);
d3.selectAll("circle").each(function(data,i) {
d3.select(this)
.attr("stroke-width", 30)
.attr("fill", function(d) {
one = parseFloat(d.value[vars['ns'][0]]);
two = parseFloat(d.value[vars['ns'][1]]);
return color(two/(one+two));
})
});
}
function changesize() {
d3.selectAll("circle").each(function(data,i) {
d3.select(this)
.transition()
.delay(0)
.duration(300)
.attr("r",
radiusScale(data.value[vars['population']]) * Math.pow(map.getZoom(),3) / 729
)
});
}
function changetooltip() {
tip = d3.tip().attr('class', 'd3-tip').html(function(d) {
html = '<span class="stronger">' + d.value[vars['name']] + "</span><br>";
html += vars['population'] + ': ' + d.value[vars['population']] + '<br>';
html += vars['ns'][1] + ': ' + d.value[vars['ns'][1]] + '<br>';
html += vars['ns'][0] + ': ' + d.value[vars['ns'][0]] + '<br>';
return html;
});
return tip;
}
function colorscale(domain,range) {
return d3.scale.linear()
.domain(domain)
.range(range);
}
function name2id(n) {
ar = n.split("-");
ar.splice(0,1);
return ar.join('-');
}
function addButtons(keys,id,btype) {
for (k in keys) {
key = keys[k];
$("#buttons-"+id).append('<label class="btn btn-'+btype+' "><input type="radio" name="options-'+id+'" id="option-'+k+'" class="switch">'+key+'</label>');
}
$('.btn').button();
}
</script>
</body>
</html>