|
<!DOCTYPE html> |
|
<meta charset="utf-8"> |
|
<head> |
|
<style> |
|
svg { |
|
} |
|
|
|
table { |
|
width: 100%; |
|
} |
|
td { |
|
|
|
vertical-align: top; |
|
} |
|
|
|
path { |
|
stroke: #fff; |
|
stroke-width: .5px; |
|
} |
|
|
|
path:hover { |
|
//stroke: black; |
|
//stroke-width: 2px |
|
} |
|
|
|
#main .zoom { |
|
fill: steelblue !important; |
|
} |
|
|
|
.caption { |
|
font-size: 30px; |
|
font-family: Verdana, Geneva, sans-serif; |
|
} |
|
|
|
line { |
|
stroke: black; |
|
stroke-opacity: 0.4 |
|
} |
|
|
|
.base { |
|
fill: #ccc; |
|
} |
|
|
|
.overlay { |
|
fill: #fa9fb5; |
|
} |
|
|
|
#andel { |
|
font-weight: bold; |
|
font-size: 1.2em; |
|
} |
|
|
|
.home { |
|
stroke: steelblue; |
|
stroke-width: 2px; |
|
} |
|
|
|
.description { |
|
font-family: Arial, Helvetica, sans-serif; |
|
} |
|
|
|
.active { |
|
stroke: green; |
|
stroke-width: 1px; |
|
} |
|
|
|
</style> |
|
|
|
<script src="//d3js.org/d3.v3.min.js"></script> |
|
<script src="//d3js.org/topojson.v1.min.js"></script> |
|
</head> |
|
|
|
<body> |
|
<div class='description'> |
|
<p> |
|
Normaliserat data för hur många som flyttar från sin hemkommun till stad vald i drop down. <br/> |
|
Färgintensitet (röd) motsvarar hur stor andel av befolkningen i en kommun som flyttat. |
|
</p> |
|
<p> |
|
Visualiseringen visar endast de kommuner där andelen som flyttat är större än <span id='andel'>XXX</span>. |
|
</p> |
|
</div> |
|
|
|
<table> |
|
<tr> |
|
<td colspan="2"> |
|
Stad: |
|
<select id="city"> |
|
<option value="0">Stockholm</option> |
|
<option value="1">Göteborg</option> |
|
<option value="2">Malmö</option> |
|
</select> |
|
</td> |
|
</tr> |
|
<tr> |
|
<td colspan=2> |
|
Kommun: <input id="search" type="search" style="width: 300px"> |
|
<input type="button" value="hitta" onclick="setKommun(this)" data-target="search"> |
|
</td> |
|
</tr> |
|
<tr> |
|
<td> |
|
<svg id='main' /> |
|
</td> |
|
<td> |
|
<pre id='detail'></pre> |
|
</td> |
|
</tr> |
|
</table> |
|
|
|
<script> |
|
|
|
// helpers |
|
d3.selection.prototype.moveToFront = function() { |
|
return this.each(function(){ |
|
this.parentNode.appendChild(this); |
|
}); |
|
}; |
|
|
|
function setKommun(d) { |
|
d3.select(".home").classed("home", false); |
|
var input = d3.select('#' + d.dataset.target); |
|
var home = d3.select('#' + (input[0][0].value)); |
|
home.classed("home", true); |
|
d3.select(home.parentNode).moveToFront(); |
|
} |
|
|
|
var distance = function distance (firstObject, secondObject) { |
|
return Math.sqrt( |
|
( firstObject[0] - secondObject[0] ) * |
|
( firstObject[0] - secondObject[0] ) + ( firstObject[1] - secondObject[1] ) * |
|
( firstObject[1] - secondObject[1] ) ); |
|
} |
|
|
|
// main code |
|
var width = 400, |
|
height = 900, |
|
min_bound = 0.05, |
|
cities = [["Stockholm","Stockholm"], |
|
["Goteborg","Göteborg"],["Malmo","Malmö"]], |
|
city = cities[0], |
|
active = d3.select(null);; |
|
|
|
d3.select("#andel").html(min_bound*100 + '%'); |
|
|
|
var projection = d3.geo.mercator() |
|
.scale(1200) |
|
.translate([width / 2, (height / 2) - 150]) |
|
.center([0, 55]) |
|
.rotate([-17, -7.4]); |
|
|
|
var path = d3.geo.path() |
|
.projection(projection); |
|
|
|
var svg = d3.select("#main") |
|
.attr("width", width) |
|
.attr("height", height); |
|
|
|
var features = ''; |
|
|
|
function update() { |
|
d3.select("#main").html(''); |
|
|
|
// setup scale |
|
var max = d3.max(features, |
|
function(d) { |
|
if(d.properties.KnNamn == city[0]) return 0; |
|
return +d.properties[city[0] + "_ANDELFR_NF"]; |
|
}); |
|
|
|
// scales |
|
var sizeScale = d3.scale.linear() |
|
.domain([0, max]) |
|
.range([1, 20]) |
|
.clamp(true); |
|
|
|
var colorScale = d3.scale.linear() |
|
.domain([0, max]) |
|
.range(['#ccc', 'red']); |
|
|
|
var groups = svg.append('g').classed('container',true).selectAll("g") |
|
.data(features) |
|
.enter() |
|
.append('g') |
|
.on("mouseover", function(d) { |
|
d3.select(this).moveToFront(); |
|
d3.select("#detail").html(JSON.stringify(d3.select(this).datum().properties, null, 2)); |
|
}); |
|
|
|
groups |
|
.classed("base", function(d) { return +d.properties[city[0] + "_ANDELFR_NF"] < min_bound; }) |
|
.classed("overlay", function(d) { return +d.properties[city[0] + "_ANDELFR_NF"] >= min_bound; }) |
|
.append("path") |
|
.attr("d", path) |
|
.style("fill", function(d) { |
|
if(+d.properties[city[0] + "_ANDELFR_NF"] < min_bound) return colorScale.range()[0]; |
|
return colorScale(+d.properties[city[0] + "_ANDELFR_NF"]); |
|
}) |
|
.attr("id", function(d) { return d.properties.KnNamn; }) |
|
.on("click", clicked) |
|
} |
|
|
|
d3.json("alla_lan(1).json", function(error, topology) { |
|
if (error) throw error; |
|
console.log(topology); |
|
features = topojson.feature(topology, topology.objects.svenskarna_kommun).features; |
|
update(); |
|
}); |
|
|
|
d3.select("#city").on("change", function() { |
|
city = cities[d3.select(this).node().value]; |
|
update(); |
|
}) |
|
|
|
|
|
function clicked(d) { |
|
if (active.node() === this) return reset(); |
|
|
|
active.classed("active", false); |
|
active = d3.select(this).classed("active", true); |
|
|
|
var bounds = path.bounds(d), |
|
dx = bounds[1][0] - bounds[0][0], |
|
dy = bounds[1][1] - bounds[0][1], |
|
x = (bounds[0][0] + bounds[1][0]) / 2, |
|
y = (bounds[0][1] + bounds[1][1]) / 2, |
|
scale = .4 / Math.max(dx / width, dy / height), |
|
translate = [width / 2 - scale * x, height / 2 - scale * y]; |
|
|
|
var g = svg.select('.container'); |
|
g.transition() |
|
.duration(750) |
|
.style("stroke-width", 1.5 / scale + "px") |
|
.attr("transform", "translate(" + translate + ")scale(" + scale + ")"); |
|
} |
|
|
|
function reset() { |
|
active.classed("active", false); |
|
active = d3.select(null); |
|
|
|
var g = svg.select('.container'); |
|
g.transition() |
|
.duration(750) |
|
.style("stroke-width", "1.5px") |
|
.attr("transform", ""); |
|
|
|
} |
|
|
|
|
|
</script> |