Skip to content

Instantly share code, notes, and snippets.

@Pabloska
Last active August 29, 2015 14:24
Show Gist options
  • Save Pabloska/af0137eb3d4919e7ff7b to your computer and use it in GitHub Desktop.
Save Pabloska/af0137eb3d4919e7ff7b to your computer and use it in GitHub Desktop.
15 years of migrant deaths - Overview (2000 - 2015)
Display the source blob
Display the rendered blob
Raw
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Leaflet Prop Symbol Map</title>
<meta name="viewport" content="width=device-width">
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7.2/leaflet.css" />
<style>
body {
font-family: sans-serif;
}
h2 {
font-size: 1.2em;
margin-top: 3px;
}
h2,div, span {
/* make text unselectable */
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
#wrapper {
width: 960px;
margin: 0 auto;
}
#map {
width: 100%;
height: 400px;
margin: 0 auto;
}
.legend, .temporal-legend {
padding: 6px 10px;
font: 14px/16px Arial, Helvetica, sans-serif;
background: white;
background: rgba(255,255,255,0.8);
box-shadow: 0 0 15px rgba(0,0,0,0.2);
border-radius: 5px;
opacity: 0.6;
}
#legendTitle {
text-align: center;
margin-bottom: 13px;
font-variant: small-caps;
}
.symbolsContainer {
float: center;
margin-left: 40px;
padding: 0.3cm 0.9cm 0.1cm 0.8cm;
}
.legendCircle {
border-radius:50%;
border: 1.5px solid red;
background: rgba(255,0,0, .5);
margin: 4px, 10;
display: inline-block;
left: 1px;
opacity: 1;
}
.legendValue {
position: absolute;
right: 5px;
}
.range-slider {
width: 150px;
}
.temporal-legend {
font-size: 1.2em;
text-align: center;
}
</style>
</head>
<body>
<div id="wrapper">
<div id="map"></div>
<div style="float:left;top:25; background-color:black;alpha(opacity=40); color:white; padding:1px; ">
<img src="http://migrantreport.org/wp-content/uploads/deths_graph.png" style="float:left;width:215px;height:110px;padding:8px 20px 1px 8px">
<img src="http://migrantreport.org/wp-content/uploads/migrant-report-red-2x.png" style="float:right;width:110px;height:20px;padding:15px 37px 5px 20px">
<h2 style="padding:10px 5px 0px 5px">15 years of migrant deaths - Overview (2000 - 2015)</h2>
<p style="font-size:12px;">This map shows the distribution of migrant deaths on their way to Europe. Move the slider to see how the picture changes depending on the year. At the beginning of the century, 60% of the deaths occurred through West African routes, whereas since 2011 more than 80% of fatalities occurred exclusively through the Central Mediterranean route (towards Italy and Malta).</p>
<a style="font-size:9px; padding:0px 2px 2px 0px;float:right;color:white;" href="http://www.themigrantsfiles.com/">Source: The Migrants' Files</a>
</div>
</div><!-- end wrapper -->
<script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="http://cdn.leafletjs.com/leaflet-0.7.2/leaflet.js"></script>
<script>
$(document).ready(function() {
var cities,
map = L.map('map', {
center: [31.757087, 10.772775],
zoom: 4,
minZoom: 4
});
L.tileLayer(
'http://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}.png', {
attribution: 'Acetate tileset from GeoIQ'
}).addTo(map);
$.getJSON('deaths_2.json')
.done(function(data) {
var dataInfo = processData(data);
createPropSymbols(dataInfo.timestamps, data);
createLegend(dataInfo.min,dataInfo.max);
createSliderUI(dataInfo.timestamps);
})
.fail(function() { alert("There has been a problem loading the data.")});
function processData(data) {
var timestamps = [],
min = Infinity,
max = -Infinity;
for (var feature in data.features) {
var properties = data.features[feature].properties;
for (var attribute in properties) {
if ( attribute != 'id' &&
attribute != 'name' &&
attribute != 'lat' &&
attribute != 'lon' )
{
if ( $.inArray(attribute,timestamps) === -1) {
timestamps.push(attribute);
}
if (properties[attribute] < min) {
min = properties[attribute];
}
if (properties[attribute] > max) {
max = properties[attribute];
}
}
}
}
return {
timestamps : timestamps,
min : min,
max : max
}
} // end processData()
function createPropSymbols(timestamps, data) {
cities = L.geoJson(data, {
pointToLayer: function(feature, latlng) {
return L.circleMarker(latlng, {
fillColor: "red",
color: 'red',
weight: 0.2,
fillOpacity: 0.3
});
}
}).addTo(map);
updatePropSymbols(timestamps[0]);
} // end createPropSymbols()
function updatePropSymbols(timestamp) {
cities.eachLayer(function(layer) {
var props = layer.feature.properties,
radius = calcPropRadius(props[timestamp]),
popupContent = "<b>" + String(props[timestamp]) + " deaths</b><br>" +
"<i>" + props.name ;
layer.setRadius(radius);
layer.bindPopup(popupContent, { offset: new L.Point(0,-radius) });
layer.on({
mouseover: function(e) {
this.openPopup();
this.setStyle({color: 'white'});
},
mouseout: function(e) {
this.closePopup();
this.setStyle({color: '#537898'});
}
});
});
} // end updatePropSymbols
function calcPropRadius(attributeValue) {
var scaleFactor = 2, // value dependent upon particular data set
area = attributeValue * scaleFactor;
return Math.sqrt(area/Math.PI)*2;
} // end calcPropRadius
function createLegend(min, max) {
if (min < 10) {
min = 10;
}
function roundNumber(inNumber) {
return (Math.round(inNumber/10) * 10);
}
var legend = L.control( { position: 'bottomright' } );
legend.onAdd = function(map) {
var legendContainer = L.DomUtil.create("div", "legend"),
symbolsContainer = L.DomUtil.create("div", "symbolsContainer"),
classes = [roundNumber(min), roundNumber((max-min)/2), roundNumber(max)],
legendCircle,
diameter,
diameters = [];
L.DomEvent.addListener(legendContainer, 'mousedown', function(e) { L.DomEvent.stopPropagation(e); });
$(legendContainer).append("<h2 id='legendTitle'> No. of Deaths</h2>");
for (var i = 0; i < classes.length; i++) {
legendCircle = L.DomUtil.create("div", "legendCircle");
diameter = calcPropRadius(classes[i])*2;
diameters.push(diameter);
var lastdiameter;
if (diameters[i-1]){
lastdiameter = diameters[i-1];
} else {
lastdiameter = 0;
};
$(legendCircle).attr("style", "width: "+diameter+"px; height: "+diameter+
"px; margin-left: -"+((diameter+lastdiameter+2)/2)+"px" );
$(legendCircle).append("<span class='legendValue'>"+classes[i]+"<span>");
$(symbolsContainer).append(legendCircle);
};
$(legendContainer).append(symbolsContainer);
return legendContainer;
};
legend.addTo(map);
} // end createLegend()
function createSliderUI(timestamps) {
var sliderControl = L.control({ position: 'bottomleft'} );
sliderControl.onAdd = function(map) {
var slider = L.DomUtil.create("input", "range-slider");
L.DomEvent.addListener(slider, 'mousedown', function(e) {
L.DomEvent.stopPropagation(e);
});
$(slider)
.attr({'type':'range', 'max': timestamps[timestamps.length-1], 'min':timestamps[0], 'step': 1,'value': String(timestamps[0])})
.on('input change', function() {
updatePropSymbols($(this).val().toString());
$(".temporal-legend").text(this.value);
});
return slider;
}
sliderControl.addTo(map);
createTemporalLegend(timestamps[0]);
} // end createSliderUI()
function createTemporalLegend(startTimestamp) {
var temporalLegend = L.control({ position: 'bottomleft' });
temporalLegend.onAdd = function(map) {
var output = L.DomUtil.create("output", "temporal-legend");
return output;
}
temporalLegend.addTo(map);
$(".temporal-legend").text(startTimestamp);
} // end createTemporalLegend()
});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment