Closed digitaltopo closed 5 years ago
The as mentioned above, the GIBS api has an endpoint that let's us request all the available datasets:
We're using the EPSG:3857
or "Web Mercator" projection for our map, so compatible results will be found at:
REST GetCapabilities endpoint for EPSG:3857: gibs.earthdata.nasa.gov/wmts/epsg3857/best/1.0.0/WMTSCapabilities.xml
which we get from the GIBS API Developers doc
The format which that api delivers data in is in xml
which isn't very friendly for our app to use. Thankfully the web mapping library we're using, OpenLayers, has a great utility to parse those options and give us back some JSON
we can use in the app!
In OpenLayers, this is done by using an instance of the WMTSCapabilities class. There isn't much on it in the docs, but they have a great example that shows us how to use this!
The important parts are making an async
request to the API by using the browser fetch api, which processes the request to a remote API and returns a promise with the results! (basically its a variable that can exist and wait for the "promised" data once it's available, in this case, once the request to the api comes back successfully!)
One caveat with fetch
is it may not be supported in older browsers, so it's smart to add a polyfill
on our app that grabs it for anyone that doesn't have it available. We can use polyfill.io to implement this, by adding the line to our html scripts section in the <head>
of our index.html
:
<script src="https://cdn.polyfill.io/v2/polyfill.js?features=fetch"></script>
Back to our actual request:
First we need to make an actual request to the correct url, which we have from the GIBS docs. Fetch requests look like this:
fetch(THE_URL_YOU_WANT_TO_FETCH)
// we chain a "then" which will fire when results come back successfully
// we pass that response as an argument into our function
.then(response => {
// we convert the response to text, because it's xml
return response.text();
})
// Next we do something with our text!
.then(text => {
// DO STUFF HERE!
});
Now that we have the data from the API, we need to parse it!
So we need to make an instance of the parser so it can understand what's coming back from the API:
const parser = new WMTSCapabilities();
So in the "//DO STUFF HERE" section above, where we process the text we got back from api, let's use our parser
to make sense of the text, and save it into a variable called result
:
...
.then(text => {
const result = parser.read(text);
});
Now we have parsed the capabilities from the api! So how do we use that? We have a couple options:
json
using JSON.stringify
and then return it from our function:...
// Parse the response text
const result = parser.read(text);
// Create JSON object from result
const json = JSON.stringify(result, null, 2);
return json
...
Quick note, we should probably put this whole fetch utility in it's own function (we could put it in the /Components/Map/utils.js
file for example), in which case if we want the function to return something, we actually also need to return the whole fetch part too. Ex):
export const fetchGibsCatalog = () => {
return fetch(...);
}
Her is a gist of what the final GIBS capabilities json object we created looks like at so we can understand the structure of it in order to extract what we want, which is the layers list and all their properties.
Here's a gist of an individual layer from that list, to demonstrate what all data we are getting back about the layer.
So now we have that json of the capabilities and layers available, maybe we can add it to our map state and hook our layers list up to populate items from there, and then read that whenever we build our tile layers.
Identifier
(from the layer list we got from the capabilities) as the layer
option in the function. We could refactor our function to use this instead, which should be able to give us what we need to update our map layer source
when we change what data set we want to view!To better let OpenLayers handle all of this for us, we could switch out the current xyz
layer to use a TileLayer with the openlayers WMTS source.
Here's an example of WMTS layer in action, although you'll notice that here the source
property and all it's options are hardcoded in, so they do some extra work to calculate a tileGrid
, but we'd have all those options directly from the API using the optionsFromCapabilities
function we described above.
Some of this part may require some more familiarity with web mapping and specifically the OpenLayers library, but we can do the fetch part first then work together to learn and implement the second part together!
Instead of hard coding our datasets, we can make a request to the GIBS API (NASA Global Imagery Browse Services) to dynamically populate the datasets.
Resources
Notes
We currently use OpenLayers as our web mapping library
Currently we're using
Web Mercator - EPSG:3857
ProjectionThe service endpoints will tell us which datasets are available: https://wiki.earthdata.nasa.gov/display/GIBS/GIBS+API+for+Developers#GIBSAPIforDevelopers-ImageryAPI/Services
REST GetCapabilities
endpoint forEPSG:3857
: https://gibs.earthdata.nasa.gov/wmts/epsg3857/best/1.0.0/WMTSCapabilities.xmlTasks
[ ] Make an async fetch request to the GIBS api
[ ] Store request results ( App state)
[ ] Handle any "loading" times while we wait for request response (maybe preload a few first if loading is slow for the entire list)
[ ] Parse results for display in list and selection interaction
[ ] Make sure results include all necessary info we need to construct tile layer urls, and pass that info to the tile layer/url constructor
[ ] Refactor the list to be more user friendly and look better visually ex) a horizontal scrolling list of thumbnails for each data set?
[ ] Document GIBS data source in wiki (Create a data sources page)