Mapbox – Visualizing the earthquakes on world map
In this blog post, I will show you how to visualize earthquakes on a world map using Mapbox.
We have seen, how to render the world map on the browser using Mapbox service in of our previous blog post. We will extend the same code to visualize the earthquakes on the map.
Create react application using the steps mentioned in the linked post or you can clone the repo from GitHub.
We can obtain the earthquake information using the following URL provided by the U.S. Geological Survey.
The information returned by URL is in the format of GeoJSON.
GeoJSON is a geospatial data interchange format based on JavaScript Object Notation (JSON). It defines several types of JSON objects and
the manner in which they are combined to represent data about geographic features, their properties, and their spatial extents.
GeoJSON uses a geographic coordinate reference system
GeoJSON supports Point, LineString, Polygon, MultiPoint, MultiLineString, and MultiPolygon geometry types.
Following JSON object represents a point on the map at given longitude and latitude
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {
prop1: xx,
prop2 : "yy"
},
"geometry": {
"type": "Point",
"coordinates": [
longitude,
latitude,
elevation
]
}
}
]
}
Code language: Java (java)
GeoJSON format can also represent LineString, Polygon, MultiPoint, MultiLineString, and MultiPolygon using GeoJSON. You can experiment with GeoJSON editor to create different representations.
In GeoJSON format
“geometry” – section contains the type of geometry and longitude and latitude where it should form.
“properties” – section will have user-defined properties, it is used to carry some data.
A sample response from USGS URL will look like below."geometry
” section contains earthquake co-ordinates,
“properties"
sections contain information about earthquake like magnitude, place and time
{
"type":"FeatureCollection",
"metadata":{
...
},
"features":[
{
"type":"Feature",
"properties":{
"mag":6.9,
"place":"central Mid-Atlantic Ridge",
"time":1600465439448,
"updated":1600494397132,
....
},
"geometry":{
"type":"Point",
"coordinates":[
-26.8495,
0.9454,
10
]
},
"id":"us7000bq10"
}
}
Code language: Java (java)
Now let’s write code to visualize the earthquakes on the map.
Add earthquake data as source in map load event callback method
map.on("load", () => {
setMap(map);
map.resize();
map.addSource("earthquakes", {
type: "geojson",
data:
"https://earthquake.usgs.gov/fdsnws/event/1/query?format=geojson&eventtype=earthquake&minmagnitude=2&starttime=" +
prevWeekDate,
generateId: true, // This ensures that all features have unique IDs
});
});
Code language: JavaScript (javascript)
Next, to display the earthquake points we need to add them as a layer to the map. We will display earthquake locations as circles on the map using below code
map.addLayer({
id: "earthquakes-viz",
type: "circle",
source: "earthquakes",
paint: {
"circle-radius": 5,
"circle-color": "#AAAAAA",
"circle-stroke-color": "#000",
"circle-stroke-width": 1,
},
});
Code language: JavaScript (javascript)
- id – unique id assigned to the layer
- type – shape to draw on corresponding locations
- source – data source name to read the data ( In this example add the data source name given in above step).
- paint – define how data for that layer is styled.
Now start the application using npm start
command and you should see the map like below with earthquake locations represented by circles.
Now we will add events to earthquake points.
Whenever we hover a mouse pointer on circles.
1. We will change the circle size and colour corresponding to its magnitude
2. Show the earthquake info like magnitude, place name and time on the screen
First we will change the layer code like below
map.addLayer({
id: "earthquakes-viz",
type: "circle",
source: "earthquakes",
// paint: {
// "circle-radius": 5,
// "circle-color": "#AAAAAA",
// "circle-stroke-color": "#000",
// "circle-stroke-width": 1,
// },
paint: {
"circle-radius": [
"case",
["boolean", ["feature-state", "hover"], false],
[
"interpolate",
["linear"],
["get", "mag"],
1,
8,
1.5,
10,
2,
12,
2.5,
14,
3,
16,
3.5,
18,
4.5,
20,
6.5,
22,
8.5,
24,
10.5,
26,
],
5,
],
"circle-stroke-color": "#000",
"circle-stroke-width": 1,
// The feature-state dependent circle-color expression will render
// the color according to its magnitude when
// a feature's hover state is set to true
"circle-color": [
"case",
["boolean", ["feature-state", "hover"], false],
[
"interpolate",
["linear"],
["get", "mag"],
1,
"#fff7ec",
1.5,
"#fee8c8",
2,
"#fdd49e",
2.5,
"#fdbb84",
3,
"#fc8d59",
3.5,
"#ef6548",
4.5,
"#d7301f",
6.5,
"#b30000",
8.5,
"#7f0000",
10.5,
"#000",
],
"#AAA",
], // end of circle color
}, // end of paint
}); //layer
Code language: JavaScript (javascript)
- Define boolean feature-state hover property and set to false by default.
- For circle-colour and circle-radius define values corresponding to their magnitude.
For displaying earthquake info declare div and corresponding style class.
.quakeInfo {
position: absolute;
font-family: sans-serif;
margin-top: 5px;
margin-left: 5px;
padding: 5px;
width: 30%;
border: 2px solid black;
font-size: 14px;
color: #222;
background-color: #fff;
border-radius: 3px;
z-index: 2;
}
Code language: JavaScript (javascript)
<>
<div ref={(el) => (mapContainer.current = el)} style={styles} />
<div className="quakeInfo">
<div>
<strong>Magnitude:</strong> <span id="mag">{earthquakeInfo.mag}</span>
</div>
<div>
<strong>Location:</strong> <span id="loc">{earthquakeInfo.loc}</span>
</div>
<div>
<strong>Date:</strong> <span id="date">{earthquakeInfo.date}</span>
</div>
</div>
</>
Code language: JavaScript (javascript)
Now we will add mouse events to map to change the colour and size of the circle on hover. Whenever the mouse moves over the earthquake layer, capture the event and if that point is corresponding to earthquake then we will change hover property to true, which results in a change of size and colour of the circle.
let quakeID = null;
map.on("mousemove", "earthquakes-viz", (e) => {
map.getCanvas().style.cursor = "crosshair";
// Set variables equal to the current feature's magnitude, location, and time
let quakeMagnitude = e.features[0].properties.mag;
let quakeLocation = e.features[0].properties.place;
let quakeDate = new Date(e.features[0].properties.time);
// Check whether features exist
if (e.features.length > 0) {
setEarthquakeInfo({
mag: quakeMagnitude,
loc: quakeLocation,
date: quakeDate.toISOString(),
});
// If quakeID for the hovered feature is not null,
// use removeFeatureState to reset to the default behavior
if (quakeID) {
map.removeFeatureState({
source: "earthquakes",
id: quakeID,
});
}
quakeID = e.features[0].id;
// When the mouse moves over the earthquakes-viz layer, update the
// feature state for the feature under the mouse
map.setFeatureState(
{
source: "earthquakes",
id: quakeID,
},
{
hover: true,
}
);
map.on("mouseleave", "earthquakes-viz", (e) => {
if (quakeID) {
map.setFeatureState(
{
source: "earthquakes",
id: quakeID,
},
{
hover: false,
}
);
}
quakeID = null;
setEarthquakeInfo({ mag: "", loc: "", date: "" });
// Reset the cursor style
map.getCanvas().style.cursor = "";
});
}
});
Code language: JavaScript (javascript)
After all the above changes whenever a user places the mouse over a circle you should use the result like below.
You can download source code for the example from GitHub