|
<!DOCTYPE html> |
|
<html> |
|
<head> |
|
<title>Testmap</title> |
|
<meta charset="utf-8" /> |
|
<script src="http://d3js.org/d3.v3.min.js"></script> |
|
<script src="http://d3js.org/topojson.v1.min.js"></script> |
|
<style> |
|
#states{ |
|
overflow-x: auto; |
|
overflow-y: auto; |
|
padding-bottom: 15px; |
|
max-width: 100%; |
|
} |
|
|
|
</style> |
|
</head> |
|
<body> |
|
<div id='states'></div> |
|
<div>Sorted list of german states</div> |
|
<div id='infos'></div> |
|
<script> |
|
var sWidth = 50 |
|
var width = 16*sWidth, |
|
height = sWidth+20 |
|
duration = 2000; |
|
|
|
var svg = d3.select("#states").append("svg") |
|
.attr("width", width) |
|
.attr("height", height); |
|
var svgInfos = d3.select("#infos").append("svg") |
|
.attr("width", width) |
|
.attr("height", 350); |
|
|
|
var path = d3.geo.path().projection(normalize_projection); |
|
var bounds; |
|
var scaleLat = d3.scale.linear(); |
|
var scaleLng = d3.scale.linear(); |
|
|
|
d3.json("vg1000_topo.json", function(error, topology) { |
|
var states = topojson.feature(topology, topology.objects.vg1000_bld); |
|
var geoms_ = states.features; |
|
//add a ID to the geometries, as I need it for the .enter() |
|
geoms_ = geoms_.map(function(d,i){d.ID=i; return d;}) |
|
|
|
showGeoms(); |
|
|
|
svg.on('mousedown',showGeoms) |
|
|
|
function showGeoms(){ |
|
//dummy re-creation of geoms array ... replace this by a filtering |
|
var geoms = geoms_.slice(0, Math.floor(Math.random() * 16)) |
|
|
|
console.log(geoms) |
|
//sort geometry for a certain property of the input geometry |
|
geoms = sortPolygons(geoms,'EWZ'); //Possible values: Length EWZ Area |
|
|
|
var elements = geoms.map(function(d){return d.ID}) |
|
|
|
//1. JOIN ... strangly, it doesn't work with the 'objects' |
|
var states = svg.selectAll('path').data(elements, function(d) { return d; }); |
|
//2. UPDATE |
|
states.transition().duration(duration) |
|
.attr("transform",function(d,i){return "translate("+(i+1)*sWidth+",0) scale(-1,1)"}) |
|
.attr('stroke','#0f0'); |
|
//3. ENTER |
|
states.enter().append('g').append("path") |
|
.attr("d",setPath) //see function... |
|
.attr('fill','#aaa') |
|
.attr('stroke','#f00') |
|
.transition().duration(duration) |
|
.attr("transform",function(d,i){return "translate("+(i+1)*sWidth+",0) scale(-1,1)"}); |
|
//5. EXIT |
|
states.exit() |
|
.transition().duration(duration) |
|
.attr("transform",function(d,i){return "translate("+sWidth*16+",0) scale(1,1)"}) |
|
.remove(); |
|
|
|
showInfo(geoms, elements, 'EWZ'); |
|
|
|
function setPath(d,i){ |
|
var geometry = geoms[i].geometry; |
|
bounds=d3.geo.bounds(geometry); //save bounds globally |
|
var new_path = path({type: geometry.type, coordinates: geometry.coordinates}) |
|
return new_path; |
|
} |
|
} |
|
function showInfo(geoms__, elements_, prop){ |
|
var startX = -500, yOffset = 20; |
|
//1. JOIN |
|
var infos = svgInfos.selectAll('text').data(elements_, function(d) { return d; }); |
|
//2. UPDATE |
|
infos.text(function (d,i){var props = geoms__[i].properties; return i + ". " + props.GEN + " has " + props.EWZ + " inhabitants!"}).transition().duration(duration) |
|
.attr('y',function(d,i){return (i+1)*yOffset}) |
|
.attr('fill','#000') |
|
//3. ENTER |
|
infos.enter().append('text') |
|
.attr('y',function(d,i){return (i+1)*yOffset}) |
|
.attr('x',startX) |
|
.text(function (d,i){var props = geoms__[i].properties; return (i+1) + ". " + props.GEN + " has " + props.EWZ + " inhabitants!"}) |
|
.transition().duration(duration) |
|
.attr('x',20) |
|
.attr('fill','#f00'); |
|
//5. EXIT |
|
infos.exit().transition().duration(duration).attr('x',startX).remove(); |
|
} |
|
}) |
|
|
|
function sortPolygons(data, attrib){ |
|
//push all values to an array |
|
if(attrib==='EWZ')var new_array = data.map(function(d){return d.properties.EWZ}); |
|
else if(attrib==='Area')var new_array = data.map(function(d){return d.properties.SHAPE_AREA}); |
|
else if(attrib==='Length')var new_array = data.map(function(d){return d.properties.LENGTH}); |
|
//sort the new array --> Help:http://www.javascriptkit.com/javatutors/arraysort.shtml |
|
new_array=new_array.sort(function(a,b){return b - a}); |
|
//find the related attribute in the data an push it to a new data-array |
|
var new_data = new_array.map(function(value){ |
|
var cache; |
|
data.forEach(function(d){ |
|
if(attrib==='EWZ'){if(value===d.properties.EWZ)cache=d} |
|
else if(attrib==='Area'){if(value===d.properties.SHAPE_AREA)cache=d} |
|
else if(attrib==='Length'){if(value===d.properties.LENGTH)cache=d} |
|
}) |
|
//return the found dataset to the new data-array |
|
return cache; |
|
}) |
|
//return the sorted data-array |
|
return new_data; |
|
} |
|
|
|
//this projection normalizes the geometry...to fit into the div-svg |
|
function normalize_projection(x) { |
|
scaleLat.domain([bounds[0][0],bounds[1][0]]) |
|
.range([sWidth,0]); |
|
scaleLng.domain([bounds[0][1],bounds[1][1]]) |
|
.range([sWidth,0]); |
|
|
|
return [scaleLat(x[0]), scaleLng(x[1])] |
|
}//[x[0]-bounds[1][0],x[1]-bounds[1][1]];} |
|
</script> |
|
</body> |
|
</html> |