Last active
November 15, 2017 21:14
-
-
Save grovduck/bee7638e3e0b935bf059d4cd4916acc8 to your computer and use it in GitHub Desktop.
[Mapbox GL JS animated earthquakes] Code for generating animated earthquakes using GeoJSON data and Mapbox GL JS. Need a simple webserver to run, e.g. 'python -m SimpleHTTPServer 8000' #mapbox #web_mapping
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset='utf-8' /> | |
<title></title> | |
<meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' /> | |
<script src='https://api.tiles.mapbox.com/mapbox-gl-js/v0.37.0/mapbox-gl.js'></script> | |
<link href='https://api.tiles.mapbox.com/mapbox-gl-js/v0.37.0/mapbox-gl.css' rel='stylesheet' /> | |
<link href='https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,700' rel='stylesheet'> | |
<style> | |
body { | |
font: 400 15px/22px 'Source Sans Pro', 'Helvetica Neue', Sans-serif; | |
margin:0; | |
padding:0; | |
} | |
#map { position:absolute; top:0; bottom:0; width:100%; } | |
</style> | |
</head> | |
<body> | |
<style> | |
.map-overlay { | |
font: 12px/20px 'Helvetica Neue', Arial, Helvetica, sans-serif; | |
position: absolute; | |
width: 25%; | |
top: 0; | |
left: 0; | |
padding: 10px; | |
} | |
.map-overlay .map-overlay-inner { | |
background-color: #fff; | |
box-shadow:0 1px 2px rgba(0, 0, 0, 0.20); | |
border-radius: 3px; | |
padding: 10px; | |
margin-bottom: 10px; | |
} | |
.map-overlay h2 { | |
line-height: 24px; | |
display: block; | |
margin: 0 0 10px; | |
} | |
.map-overlay .legend .bar { | |
height: 10px; | |
width: 100%; | |
background: linear-gradient(to right, #FCA107, #7F3121); | |
} | |
.map-overlay input { | |
background-color: transparent; | |
display: inline-block; | |
width: 100%; | |
position: relative; | |
margin: 0; | |
cursor: ew-resize; | |
} | |
</style> | |
<div id='map'></div> | |
<div class='map-overlay top'> | |
<div class='map-overlay-inner'> | |
<div id='legend' class='legend'> | |
<div class='date'> | |
<p id='currentDate'><p> | |
</div> | |
<div class='bar'></div> | |
<div>Magnitude (m)</div> | |
</div> | |
</div> | |
</div> | |
<script src='https://d3js.org/d3.v3.min.js' charset='utf-8'></script> | |
<script> | |
mapboxgl.accessToken = 'pk.eyJ1IjoiZ3JvdmR1Y2siLCJhIjoiYXVYb29zbyJ9.TO2NcqGJDyWDCSvOfBBUIQ'; | |
var map = new mapboxgl.Map({ | |
container: 'map', | |
style: 'mapbox://styles/mapbox/light-v9', | |
center: [31.4606, 20.7927], | |
zoom: 0.5 | |
}); | |
var earthquakes; | |
var currentTimestamp; | |
map.on('load', function() { | |
d3.json("./significant-earthquakes-2015.geojson", function(err, data) { | |
if (err) throw err; | |
data.features = data.features.map(function(d) { | |
var current = new Date(d.properties.time); | |
d.properties.startAnimation = new Date(current.getTime()).setDate(current.getDate() - 5); | |
d.properties.endAnimation = new Date(current.getTime()).setDate(current.getDate() + 5); | |
d.properties.currentMag = 0; | |
return d; | |
}); | |
earthquakes = { | |
"type": "geojson", | |
"data": data | |
}; | |
map.addSource("earthquakes", earthquakes); | |
map.addLayer({ | |
'id': 'earthquake-circles', | |
'type': 'circle', | |
'source': 'earthquakes', | |
'paint': { | |
'circle-color': { | |
property: 'mag', | |
stops: [ | |
[5, '#ffff00'], | |
[6, '#FCA107'], | |
[7, '#7F3121'], | |
[8, '#7F3121'] | |
] | |
}, | |
'circle-opacity': 0.30, | |
'circle-stroke-width': 0.5, | |
'circle-radius': { | |
property: 'currentMag', | |
stops: [ | |
[0, 0], | |
[6, 15], | |
[8, 40] | |
] | |
} | |
} | |
}); | |
currentTimestamp = new Date('2015-01-01'); | |
endTimestamp = new Date('2016-01-01'); | |
delay = '200'; | |
transitionStyle = 'linear'; | |
setTimeout(function(){ | |
function animate() { | |
currentTimestamp.setHours(currentTimestamp.getHours() + 3); | |
if (currentTimestamp >= endTimestamp) { | |
currentTimestamp.setYear(2015); | |
} | |
updateCurrentDate(); | |
map.fire('move earthquakes'); | |
requestAnimationFrame(animate); | |
} | |
animate(); | |
}, 1000); | |
}); | |
}); | |
function updateCurrentDate() { | |
var p = document.getElementById('currentDate'); | |
var d = currentTimestamp; | |
var dateString = d.getFullYear() + "-" | |
+ ("0" + (d.getMonth()+1)).slice(-2) + "-" | |
+ ("0" + d.getDate()).slice(-2); | |
p.innerHTML = dateString; | |
} | |
map.on('move earthquakes', function() { | |
map.getSource('earthquakes').setData(showActiveEarthquakes()); | |
}); | |
function showActiveEarthquakes() { | |
for (var i = 0; i < earthquakes.data.features.length; i++) { | |
var marker = earthquakes.data.features[i]; | |
if (marker.properties.startAnimation <= currentTimestamp && | |
marker.properties.endAnimation >= currentTimestamp) { | |
var start = marker.properties.startAnimation; | |
var end = marker.properties.endAnimation; | |
var eTime = marker.properties.time; | |
if (currentTimestamp < eTime) { | |
var w1 = (currentTimestamp - start) / (eTime - start); | |
var w2 = 1.0 - w1; | |
var currentMag = w1 * marker.properties.mag; | |
} else if (currentTimestamp > eTime) { | |
var w1 = (currentTimestamp - eTime) / (end - eTime); | |
var w2 = 1.0 - w1; | |
var currentMag = w2 * marker.properties.mag; | |
} | |
marker.properties.currentMag = currentMag; | |
} | |
} | |
return earthquakes.data; | |
} | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment