xxxxxxxxxx
<html lang="en">
<head>
<meta charset="utf-8">
<title>EU Migration Crisis</title>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js" charset="utf-8"></script>
<script src="https://d3js.org/topojson.v1.min.js"></script>
<link href="https://fonts.googleapis.com/css?family=Roboto+Condensed:300normal,300italic,400normal,400italic,700normal,700italic|Roboto:400normal|Open+Sans:400normal|Oswald:400normal|Lato:400normal|Roboto+Slab:400normal|Open+Sans+Condensed:300normal|Source+Sans+Pro:400normal|Raleway:400normal|PT+Sans:400normal|Ubuntu:400normal&subset=all" rel="stylesheet" type="text/css">
<style type="text/css">
body {
background-color: #fff1e0;
margin-top: 3em;
font-family: 'Roboto Condensed', sans-serif;
font-weight: 400;
}
svg {
background-color: #ecf8fe;
}
h1 {
font-weight: 300;
font-size: 36px;
color: #333333;
margin-top: 0;
margin-bottom: 0;
margin-left: -2px;
}
h6 {
font-size: 12px;
margin-bottom: 0.2em;
margin-top: 6px;
font-weight: 800;
text-transform: uppercase;
color: #af516c;
}
.contentHolder {
background: #fff9f1;
padding: 20px 20px 14px;
width: 640px;
box-sizing: border-box;
margin: 0 auto;
box-shadow: 0px 2px 5px 0px rgba(0,0,0,0.3);
position: relative;
}
.coast {
stroke: #a7a592;
fill: none;
stroke-width: 1px;
}
.schengen-yes {
fill: #bddacd;
}
.schengen-no {
fill: #dfb3ae;
}
.subjectCountry{
font-weight: 700;
font-size: 1.5em;
fill: #706F6F;
letter-spacing: 2px;
}
.place-label {
font-size: 11px;
text-transform: uppercase;
text-anchor: middle;
fill: #74736c
}
.subject.place-label {
font-weight: 800;
font-size: 14px;
fill: #000000;
}
.legendLabel {
font-size: 13px;
}
.border {
stroke-linejoin: round;
stroke-linecap: round;
}
.border.additional {
stroke: #000000;
stroke-width: 3px;
}
.border.partial {
stroke: #f26522;
stroke-width: 3px;
}
.border.fence {
stroke: #ad1c21;
stroke-width: 3px;
}
.disputed {
stroke: #a7a592;
stroke-width: 1px;
stroke-dasharray:1, 2;
fill: none;
}
.arrowsHolder{
position: absolute;
bottom: 28px;
left: 12px;
opacity: 0;
}
.relief {
position: absolute;
bottom: 25px;
left: 20px;
opacity: 0;
}
.refugees circle, .legend.refugees {
fill: #af516c;
fill-opacity: 0;
stroke: #af516c;
stroke-width: 1px;
}
.refugees text{
font-weight: 400;
text-anchor: middle;
fill: #ffffff;
font-size: 13px;
letter-spacing: 1px;
opacity: 0;
}
.source {
font-size: 11px;
}
</style>
</head>
<body>
<div class="contentHolder">
<h6>EU Migration Crisis</h6>
<h1>How many refugees enter the EU via the Western Balkans route?</h1>
<p>Over the summer of 2015, an increasing number of migrants and asylum seekers escaping war, take the Western Balkans route, which stretches from Greece to northern Europe</p>
<div class="arrowsHolder"><img src="https://image.webservices.ft.com/v1/images/raw/ftcms:39099228-9130-11e5-bd82-c1fb87bef7af?source=test" alt=""></div>
<!-- <div class="relief"><img src="images/relief.png" alt=""></div> -->
<div class="mapHolder"></div>
<div class="source">Source: UNHCR; Acaps</div>
</div>
<script type="text/javascript">
//Width and height
var w = 600;
var h = 689;
//Define map projection
var projection = d3.geo.mercator()
.center([17.5, 47.4 ])
.translate([ w/2, h/2 ])
.scale([ w * 2.0]);
//Define path generator
var path = d3.geo.path()
.projection(projection);
//Create SVG
var svg = d3.select('.mapHolder')
.append('svg')
.attr('width', w)
.attr('height', h)
.attr('opacity', 0)
var numFormat = d3.format(',')
//Load in GeoJSON data
d3.json('eumigration.json', function(migration) {
// //Bind data and create one path per GeoJSON feature
var countryFills = svg.append('g');
var relief = svg.append('g');
var coast = svg.append('g');
var boundaryLines = svg.append('g');
var disputed = svg.append('g');
var refugees = svg.append('g');
var countryNames = svg.append('g');
var legend = svg.append('g');
countryFills.selectAll('path')
.data(topojson.feature(migration, migration.objects.countries).features)
.enter()
.append('path')
.attr({
'd': path,
'id': function(d) { return d['SOV_A3']; },
'class': 'country',
// 'opacity': 0.6,
'fill': function(d) {
if(d.properties.schengen === 'yes') {
return '#bddacd'
} else if (d.properties.schengen === 'no'){
return '#dfb3ae';
} else {
return '#f8f7f4';
}
},
});
boundaryLines.selectAll('path')
.data(topojson.feature(migration, migration.objects.boundaries).features)
.enter()
.append('path')
.attr({
'd': path,
'id': function(d) { return d['SOV_A3']; },
'class': function(d) { return 'boundary ' + d.properties.type; },
// 'fill-opacity': 0.4,
'fill': 'none',
'stroke-width': function(d) {
if(d.properties.type === 'additional' || d.properties.type === 'fence' || d.properties.type === 'partial') {
return 3;
} else {
return 1;
}
},
'stroke': '#a7a592',
'stroke-linejoin': 'round',
'stroke-linecap': 'round',
'stroke-width': '1px'
})
.transition().delay(5000).duration(1000).attr('stroke',
function(d) {
if(d.properties.type === 'additional') {
return '#000000'
} else if (d.properties.type === 'fence'){
return '#ad1c21';
} else if (d.properties.type === 'partial'){
return '#f26522';
} else {
return '#a7a592';
}
}
).attr('stroke-width',
function(d) {
if(d.properties.type === 'additional') {
return 3
} else if (d.properties.type === 'fence'){
return 3;
} else if (d.properties.type === 'partial'){
return 3;
} else {
return 1;
}
}
);
d3.selectAll('.additional').transition().delay(8000).duration(500).style('opacity', 0.3);
d3.selectAll('.partial').transition().delay(8000).duration(500).style('opacity', 0.3);
d3.selectAll('.fence').transition().delay(8000).duration(500).style('opacity', 0.3);
countryNames.selectAll('.place-label')
.data(topojson.feature(migration, migration.objects.clabels).features)
.enter().append('text')
.attr('class',
function(d) {
if(d.properties.feature === 'yes') {
return 'subject place-label';
} else {
return 'place-label';
}
})
.attr('transform', function(d) { return 'translate(' + projection(d.geometry.coordinates) + ')'; })
.text(function(d) { return d.properties.name; });
disputed.selectAll('path')
.data(topojson.feature(migration, migration.objects.disputed).features)
.enter()
.append('path')
.attr({
'd': path,
'class': 'disputed'
})
coast.selectAll('path')
.data(topojson.feature(migration, migration.objects.ocean).features)
.enter()
.append('path')
.attr({
'd': path,
'class': 'coast'
})
// add circle groups for refugee numbers
var refugeeData = refugees.selectAll('g')
.data(topojson.feature(migration, migration.objects.refugees).features)
.enter()
.append('g')
.attr({
'class': 'refugees'
})
.attr('transform', function(d) { return 'translate(' + projection(d.geometry.coordinates) + ')'; });
//add circles
refugeeData.append('circle')
// .attr('r', function(d) { return Math.sqrt(d.properties.refugees) / Math.PI / 8; })
.attr('r', 0)
.transition().delay(function(d, i) { return (i * 50) + 9000 ; }).duration(500).attr('r', function(d) { return Math.sqrt(d.properties.refugees) / Math.PI / 5; }).style('fill-opacity', 0.7);
//add data values
refugeeData.append('text')
.text(function(d) { return numFormat(d.properties.refugees); })
.attr('dy', 6)
.transition().delay(function(d, i) { return (i * 50) + 9000 ; }).duration(500).style('opacity', 1);;
legend.attr('transform', 'translate(' + (w - 200) + ',' + 10 + ')')
legend.append('rect')
.attr({
'width': 190,
'height': 150,
'fill': '#ffffff',
'opacity': 0
})
.transition().delay(1000).duration(500).attr('opacity', 1);
var borders = legend.append('g');
borders
.attr('transform', 'translate(' + 10 + ',' + 50 + ')')
.attr('opacity', 0)
borders.append('line')
.attr({
'x1': 0,
'x2': 30,
'y1': 5,
'y2': 5,
'class': 'border additional'
})
borders.append('line')
.attr({
'x1': 0,
'x2': 30,
'y1': 25,
'y2': 25,
'class': 'border fence'
})
borders.append('line')
.attr({
'x1': 0,
'x2': 30,
'y1': 45,
'y2': 45,
'class': 'border partial'
})
borders.append('text')
.attr('class', 'legendLabel')
.attr('transform', 'translate(' + 35 + ',' + 10 + ')')
.text('Additional border controls')
borders.append('text')
.attr('class', 'legendLabel')
.attr('transform', 'translate(' + 35 + ',' + 30 + ')')
.text('Fences')
borders.append('text')
.attr('class', 'legendLabel')
.attr('transform', 'translate(' + 35 + ',' + 50 + ')')
.text('Partial fences planned')
borders
.transition().delay(5000).duration(1000).attr('opacity', 1);
legend.append('rect')
.attr('transform', 'translate(' + 10 + ',' + 10 + ')')
.attr({
'width': 30,
'height': 10,
'class': 'legend schengen-yes',
'opacity': 0
})
.transition().delay(1000).duration(800).attr('opacity', 1);
legend.append('rect')
.attr('transform', 'translate(' + 10 + ',' + 30 + ')')
.attr({
'width': 30,
'height': 10,
'class': 'legend schengen-no',
'opacity': 0
})
.transition().delay(1000).duration(800).attr('opacity', 1);
legend.append('circle')
.attr('transform', 'translate(' + 25 + ',' + 125 + ')')
.attr({
'r': 15,
'class': 'legend refugees',
'opacity': 0
})
.transition().delay(9000).duration(800).attr('opacity', 1).style('fill-opacity', 0.7);
legend.append('text')
.attr('transform', 'translate(' + 45 + ',' + 20 + ')')
.attr('class', 'legendLabel')
.attr('opacity', 0)
.text('Schengen countries')
.transition().delay(1000).duration(800).attr('opacity', 1);
legend.append('text')
.attr('transform', 'translate(' + 45 + ',' + 40 + ')')
.attr('class', 'legendLabel')
.attr('opacity', 0)
.text('Non-Schengen countries')
.transition().delay(1000).duration(800).attr('opacity', 1);
var legendRefugeeLabel = legend.append('text')
.attr('transform', 'translate(' + 45 + ',' + 122 + ')')
.attr('class', 'legendLabel')
.attr('opacity', 0);
legendRefugeeLabel.append('tspan')
.text('Estimated arrivals');
legendRefugeeLabel.append('tspan')
.text('since Sept 1 2015')
.attr('x', 0)
.attr('y', 15);
// <image xlink:href="firefox.jpg" x="0" y="0" height="50px" width="50px"/>
relief.append('image')
.attr({
'xlink:href': 'https://image.webservices.ft.com/v1/images/raw/ftcms:ccbe9dec-9135-11e5-bd82-c1fb87bef7af?source=test',
'width': 600,
'height': 690
})
/* transitions*/
svg.transition().delay(200).duration(800).attr('opacity', 1);
// d3.select('.arrowsHolder').transition().delay(3000).duration(800).attr('opacity', 1);
d3.select('.arrowsHolder').transition().delay(3000).duration(800).style('opacity', 1);
d3.select('.arrowsHolder').transition().delay(7000).duration(800).style('opacity', 0.3);
legendRefugeeLabel.transition().delay(9000).duration(800).attr('opacity', 1);
});
</script>
</body>
</html>
Modified http://d3js.org/topojson.v1.min.js to a secure url
https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js
https://d3js.org/topojson.v1.min.js