index.html
<!DOCTYPE html>
<html>
<head>
<title>Zelení + Piráti + Změna 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/journal/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: 90%;
}
circle {
cursor: pointer;
fill-opacity: 0.8;
stroke-opacity: 0.01;
}
circle:hover {
stroke-opacity: 1;
}
.towns {
width: 100000px;
height: 100000px;
}
svg:not(:root) {
overflow: visible;
}
.d3-tip {
line-height: 1;
padding: 12px;
background: rgba(0, 0, 0, 0.8);
color: #fff;
border-radius: 2px;
}
.d3-tip small {
font-size: 0.5em;
}
.d3-tip.n:after {
margin: -1px 0 0 0;
top: 100%;
left: 0;
}
.stronger {
color: yellow;
font-weight: bold;
}
.navbar {
margin-bottom: 0;
}
</style>
</head>
<body>
<div class="navbar navbar-default" role="navigation">
<div class="container">
<div class="navbar-header">
<a class="navbar-brand">Zelení + Piráti + Změna 2013</a>
</div>
</div>
</div>
<div class="btn-group" role="group" aria-label="kraje">
<a class="btn btn-primary regions" href="#" role="button" value="Jihočeský kraj">Jihočeský</a>
<a class="btn btn-primary regions" href="#" role="button" value="Jihomoravský kraj">Jihomoravský</a>
<a class="btn btn-primary regions" href="#" role="button" value="Karlovarský kraj">Karlovarský</a>
<a class="btn btn-primary regions" href="#" role="button" value="Královéhradecký kraj">Královéhradecký</a>
<a class="btn btn-primary regions" href="#" role="button" value="Liberecký kraj">Liberecký</a>
<a class="btn btn-primary regions" href="#" role="button" value="Moravskoslezský kraj">Moravskoslezský</a>
<a class="btn btn-primary regions" href="#" role="button" value="Olomoucký kraj">Olomoucký</a>
<a class="btn btn-primary regions" href="#" role="button" value="Pardubický kraj">Pardubický</a>
<a class="btn btn-primary regions" href="#" role="button" value="Plzeňský kraj">Plzeňský</a>
<a class="btn btn-primary regions" href="#" role="button" value="Středočeský kraj">Středočeský</a>
<a class="btn btn-primary regions" href="#" role="button" value="Ústecký kraj">Ústecký</a>
<a class="btn btn-primary regions" href="#" role="button" value="Kraj Vysočina">Vysočina</a>
<a class="btn btn-primary regions" href="#" role="button" value="Zlínský kraj">Zlínský</a>
</div>
<div style="position:fixed;top:125px;z-index:1000;">
<div class="alert alert-info" style="float:left;" id="legend">
<h3>Zelení+Piráti+Změna</h3>
<svg height="20" width="20"><circle cx="10" cy="10" r="10" fill="blue"></svg> 10 %<br/>
<svg height="20" width="20"><circle cx="10" cy="10" r="10" fill="green"></svg> 6.4 %<br/>
<svg height="20" width="20"><circle cx="10" cy="10" r="10" fill="yellow"></svg> 5 %<br/>
<svg height="20" width="20"><circle cx="10" cy="10" r="10" fill="red"></svg> 0 %<br/>
</div>
</div>
<div id="map"></div>
<script type="text/javascript">
var map = L.map('map', {'zoomControl':false}).setView([50,15], 8);
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 | <a href="//ovolby.cz">ovolby.cz</a>'
}).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, 586509]).range([0, 75]);
var color = colorscale([0,0.05,0.0641,0.1,1],["red", "yellow", "green", "blue", "darkblue"]);
var tip = changetooltip();
svg.call(tip);
var div = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 1e-6);
d3.csv('cz_towns.csv', function(data) {
d3.csv('sz_pirati_zmena_2013.csv',function(results_arr) {
results = {};
for (i=0;i<results_arr.length;i++) {
results[results_arr[i]['id']] = results_arr[i];
}
nodes = data
.map(function(d) {
mpoint = projectPoint(d.lat,d.long);
ret = {
x: mpoint.x,
y: mpoint.y,
name: d.name,
value: d
};
if (typeof(results[d.id]) != 'undefined') {
ret['results'] = results[d.id];
ret['r'] = radiusScale(results[d.id]["total"]);
}
return ret;
});
var circle = svg.selectAll("svg")
.data(nodes)
.enter().append("svg:svg")
.append("svg:circle")
.attr("class","town")
.attr("id", function (d) {return "id_" + d.value.id})
.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) {
if (typeof(d.results) != 'undefined') {
return color(parseFloat(d.results['sz_pirati_zmena'])/d.results['total']);
} else {
return '#ccf';
}
})
.on("mouseover", tip.show)
.on("mouseout", tip.hide);
map.on("viewreset", changeit);
map.on("moveend", changeit);
map.on("zoomstart", hidepoints);
$(".towns").show(100);
});
});
function matrixVal(s) {
return s.split('(')[1].split(')')[0].split(',');
}
function hidepoints() {
$(".towns").hide();
}
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(".town").each(function(d,i) {
mpoint = projectPoint(d.value.lat,d.value.long,d.value.id);
$(this)
.attr("r",
function() {
if (typeof(d.results) != 'undefined')
return radiusScale(d.results["total"]) * Math.pow(map.getZoom(),4) / 4096;
else
return 0;
}
)
.attr("cx", mpoint.x)
.attr("cy", mpoint.y);
$(this).attr('transform',"translate(" + sar[4] + "," + sar[5] + ")");
});
$(".towns").show(300);
}
function projectPoint(x, y, id) {
var point = map.latLngToLayerPoint(new L.LatLng(x, y));
if (!isNumeric(point.x)) alert(id);
return point;
}
function changetooltip() {
tip = d3.tip().attr('class', 'd3-tip').html(function(d) {
html = '<span class="stronger">' + d.name + "</span><br>";
if (typeof(d.results) != 'undefined') {
html += 'SZ+Piráti+Změna: '+Math.round(parseFloat(d.results.sz_pirati_zmena)/parseFloat(d.results.total)*10000)/100 + ' % (' + d.results.sz_pirati_zmena + ')<br>';
html += 'Piráti: '+Math.round(parseFloat(d.results.pirati)/parseFloat(d.results.total)*10000)/100 + ' % (' + d.results.pirati + ')<br>';
html += 'Zelení: '+Math.round(parseFloat(d.results.sz)/parseFloat(d.results.total)*10000)/100 + ' % (' + d.results.sz + ')<br>';
html += 'Změna: '+Math.round(parseFloat(d.results.zmena)/parseFloat(d.results.total)*10000)/100 + ' % (' + d.results.zmena + ')'; }
return html;
});
return tip;
}
function isNumeric(n) {
return !isNaN(parseFloat(n)) && isFinite(n);
}
function colorscale(domain,range) {
return d3.scale.linear()
.domain(domain)
.range(range);
}
$(document).ready(function() {
$(".regions").on('click',function() {
var reg = $(this);
d3.selectAll(".town").each(function(d,i) {
if (d.results.region == reg.attr('value')) {
$('#id_'+d.value.id).show();
} else {
$('#id_'+d.value.id).hide();
}
});
});
});
</script>
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-8592359-13', 'ocks.org');
ga('send', 'pageview');
</script>
</body>
</html>
chart.html
<!DOCTYPE html>
<html lang="sk">
<head>
<meta charset="utf-8">
<title>Zelení + Piráti + Změna 2013</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="WPCA scatter plot">
<meta name="author" content="Michal Škop">
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootswatch/3.2.0/journal/bootstrap.min.css">
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="//d3js.org/d3.v3.min.js"></script>
<script src="./d3.scatterplot.js"></script>
<script src="./d3.tip.js"></script>
<style type="text/css">
.tick {
fill-opacity: 0;
stroke: #000000;
stroke-width: 1;
}
.domain {
fill: none;
fill-opacity: 0;
stroke: black;
stroke-width: 1;
}
.axis line {
fill: none;
fill-opacity: 0;
stroke: black;
stroke-width: 1;
shape-rendering: crispEdges;
}
.axis text {
font-family: sans-serif;
font-size: 11px;
stroke: gray;
}
circle {
fill-opacity: .5;
fill:#080;
stroke:#080;
stroke-opacity: 0.99;
stroke-width: 1;
}
circle:hover {
fill-opacity: 1;
}
.label {
font-family: sans-serif;
font-size: 15px;
}
.stronger {
color: yellow;
font-weight: bold;
}
.d3-tip {
line-height: 1;
font-weight: bold;
padding: 12px;
background: rgba(0, 0, 0, 0.8);
color: #fff;
border-radius: 2px;
pointer-events: none;
max-width: 400px;
}
.d3-tip:after {
box-sizing: border-box;
display: inline;
font-size: 10px;
width: 100%;
line-height: 1;
color: rgba(0, 0, 0, 0.8);
position: absolute;
pointer-events: none;
}
.d3-tip:after {
content: "\25BC";
margin: -1px 0 0 0;
top: 100%;
left: 0;
text-align: center;
}
line {
stroke:gray;
stroke-width:1;
opacity: .15;
}
.centerline {
stroke: #b00;
stroke-width: 3;
stroke-opacity: 1;
}
.averageline {
stroke: #080;
stroke-width: 2;
stroke-opacity: 1;
stroke-dasharray: 10, 5;
}
#chart {
}
</style>
</head>
<body>
<h1>Zelení + Piráti + Změna 2013</h1>
<div class="btn-group" role="group" aria-label="kraje">
<a class="btn btn-primary regions" href="#" role="button" value="Jihočeský kraj">Jihočeský</a>
<a class="btn btn-primary regions" href="#" role="button" value="Jihomoravský kraj">Jihomoravský</a>
<a class="btn btn-primary regions" href="#" role="button" value="Karlovarský kraj">Karlovarský</a>
<a class="btn btn-primary regions" href="#" role="button" value="Královéhradecký kraj">Královéhradecký</a>
<a class="btn btn-primary regions" href="#" role="button" value="Liberecký kraj">Liberecký</a>
<a class="btn btn-primary regions" href="#" role="button" value="Moravskoslezský kraj">Moravskoslezský</a>
<a class="btn btn-primary regions" href="#" role="button" value="Olomoucký kraj">Olomoucký</a>
<a class="btn btn-primary regions" href="#" role="button" value="Pardubický kraj">Pardubický</a>
<a class="btn btn-primary regions" href="#" role="button" value="Plzeňský kraj">Plzeňský</a>
<a class="btn btn-primary regions" href="#" role="button" value="Středočeský kraj">Středočeský</a>
<a class="btn btn-primary regions" href="#" role="button" value="Ústecký kraj">Ústecký</a>
<a class="btn btn-primary regions" href="#" role="button" value="Kraj Vysočina">Vysočina</a>
<a class="btn btn-primary regions" href="#" role="button" value="Zlínský kraj">Zlínský</a>
</div>
<div id="chart"></div>
<p class="bg-info"><span class="glyphicon glyphicon-info-sign" aria-hidden="false"> </span> Každý bod je jedna obec. Velikost bodu reprezentuje počet voličů. Osa x je součet zisku Zelených, Pirátů a Změny (%). Osa y je jen náhodné číslo, aby graf byl přehlednější.
<footer><small>CC-BY Michal Škop, <a href="//kohovolit.eu">KohoVolit.eu</a></small></footer>
<script type="text/javascript">
var radiusScale = d3.scale.sqrt().domain([0, 586509]).range([0, 75]);
d3.csv('cz_towns.csv', function(data) {
d3.csv('sz_pirati_zmena_2013.csv',function(results_arr) {
results = {};
for (i=0;i<results_arr.length;i++) {
results[results_arr[i]['id']] = results_arr[i];
}
points = [];
data.forEach(function(d) {
if (typeof(results[d.id]) != 'undefined') {
d2 = results[d.id];
points.push({
'r' : radiusScale(d2["total"]),
'y': Math.random(),
'x': parseFloat(parseFloat(d2.sz_pirati_zmena)/d2.total),
'name': d.name,
'class': 'town id_' + d2.id,
'region': d2.region,
'id': d.id
});
}
});
var scatterplot = [{
"data": points,
"margin": {top: 10, right: 10, bottom: 30, left: 30},
"axes": {"labels":{"y":"", "x":"Zelení + Piráti + Změna 2013"}},
"minmax":{
"x":{'min':0,'max':0.2},
"y":{'min':0,'max':1},
"r":{'min':0,'max':Math.sqrt(586509)},
"rrange":{'min':0,'max':500}
},
"size":{"width":1000,"height":200},
}];
var svg = d3.select("#chart")
.append("svg")
.attr("width",scatterplot[0]['size']['width'])
.attr("height",scatterplot[0]['size']['height']);
tip = d3.tip().attr('class', 'd3-tip').html(
function(d) {
return "<span class=\'stronger\'>" + d["name"] + "</span><br>" +
'Zelení+Piráti+Změna: '+Math.round(d.x*10000)/100 + ' %';
});
svg.call(tip)
var sp = d3.scatterplot()
.data(function(d) {return d.data})
.margin(function(d) {return d.margin})
.axes(function(d) {return d.axes})
.minmax(function(d) {return d.minmax})
.size(function(d) {return d.size})
var scatter = svg.selectAll(".scatterplot")
.data(scatterplot)
.enter()
.append("svg:g")
.attr("transform", "translate(" + scatterplot[0].margin.left + "," + scatterplot[0].margin.top + ")")
.call(sp);
var line = d3.svg.line()
.x(
function(d) {
return d[0]; })
.y(function(d) { return d[1]; });
var width = scatterplot[0].size['width'] - scatterplot[0].margin.left - scatterplot[0].margin.right,
height = scatterplot[0].size['height'] - scatterplot[0].margin.top - scatterplot[0].margin.bottom;
var xScale = d3.scale.linear()
.domain([scatterplot[0].minmax['x']['min'], scatterplot[0].minmax['x']['max']])
.range([0, width])
var yScale = d3.scale.linear()
.domain([scatterplot[0].minmax['y']['min'], scatterplot[0].minmax['y']['max']])
.range([height, 0])
centerline = Array([xScale(0.05),yScale(scatterplot[0].minmax['y']['min'])],[xScale(0.05),yScale(scatterplot[0].minmax['y']['max'])]);
svg.append("path")
.datum(centerline)
.attr("class", "centerline")
.attr("d", line)
.attr("transform", "translate(" + scatterplot[0].margin.left + "," + scatterplot[0].margin.top + ")");
averageline = Array([xScale(scatterplot[0].minmax['x']['min']),yScale(21.4)],[xScale(scatterplot[0].minmax['x']['max']),yScale(21.4)]);
svg.append("path")
.datum(averageline)
.attr("class", "averageline")
.attr("d", line)
.attr("transform", "translate(" + scatterplot[0].margin.left + "," + scatterplot[0].margin.top + ")");
})
})
$(document).ready(function() {
$(".regions").on('click',function() {
var reg = $(this);
d3.selectAll(".town").each(function(d,i) {
if (d.region == reg.attr('value')) {
$('.id_'+d.id).show();
} else {
$('.id_'+d.id).hide();
}
});
});
});
</script>
</body>
</html>
d3.scatterplot.js
d3.scatterplot = function() {
function scatterplot(selection) {
selection.each(function(d, i) {
var data = (typeof(data) === "function" ? data(d) : d.data),
margin = (typeof(margin) === "function" ? margin(d) : d.margin),
axes = (typeof(axes) === "function" ? axes(d) : d.axes),
minmax = (typeof(minmax) === "function" ? minmax(d) : d.minmax),
size = (typeof(size) === "function" ? size(d) : d.size);
var width = size['width'] - margin.left - margin.right,
height = size['height'] - margin.top - margin.bottom;
var xScale = d3.scale.linear()
.domain([minmax['x']['min'], minmax['x']['max']])
.range([0, width])
var yScale = d3.scale.linear()
.domain([minmax['y']['min'], minmax['y']['max']])
.range([height, 0])
var rScale = d3.scale.linear()
.domain([minmax['r']['min'],minmax['r']['max']])
.range([minmax['rrange']['min'],minmax['rrange']['max']]);
var xAxis = d3.svg.axis()
.scale(xScale)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(yScale)
.orient("left");
var element = d3.select(this);
element.append("g")
.attr("class", "axis x-axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
element.append("g")
.attr("class", "axis y-axis")
.call(yAxis);
element.selectAll("circle")
.data(data)
.enter()
.append("circle")
.attr("cx", function(d) {
return xScale(d.x);
})
.attr("cy", function(d) {
return yScale(d.y);
})
.attr("r", function(d) {
return rScale(d.r);
})
.attr("class", function(d) {
if (typeof(d['class'] != 'undefined')) return d['class'];
else return 'circle';
})
.attr("region", function(d) {
if (typeof(d['region'] != 'undefined')) return d['region'];
else return '';
})
.on('mouseover', tip.show)
.on('mouseout', tip.hide);
element.append("text")
.attr("class", "x-label label")
.attr("text-anchor", "end")
.attr("x", width)
.attr("y", height-5)
.text(axes['labels']['x']);
element.append("text")
.attr("class", "y label")
.attr("text-anchor", "end")
.attr("y", 5)
.attr("x", 0)
.attr("dy", ".75em")
.attr("transform", "rotate(-90)")
.text(axes['labels']['y']);
});
}
scatterplot.data = function(value) {
if (!arguments.length) return value;
data = value;
return scatterplot;
};
scatterplot.margin = function(value) {
if (!arguments.length) return value;
margin = value;
return scatterplot;
};
scatterplot.axes = function(value) {
if (!arguments.length) return value;
axes = value;
return scatterplot;
};
scatterplot.minmax = function(value) {
if (!arguments.length) return value;
minmax = value;
return scatterplot;
};
scatterplot.size = function(value) {
if (!arguments.length) return value;
size = value;
return scatterplot;
};
return scatterplot;
}
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
};
}));
script.py
import csv
import json
with open("cz2014towns.json") as fin:
towns = json.load(fin)
with open("cz_towns.csv","w") as fout:
header = ['id','name','lat','long']
csvdw = csv.DictWriter(fout,fieldnames=header)
csvdw.writeheader();
for town in towns:
row = {
'id': town['id'],
'name': town['name'],
'lat': town['lat'],
'long': town['lng']
}
csvdw.writerow(row)