NationalMap is an intuitive interface that allows you to explore and filter a vast collection of geographic data. Convivial is a distribution that extends GovCMS with a NationalMap Component. In this article we will walkthrough embedding a national map without a single line of code, and show you how we built it.
NationalMap Component
In Convivial we have created a "NationalMap" paragraph which allows you to augment geo data from multiple data sources onto the one map. Geo data can be sourced from nationalmap.gov.au, data.gov.au or by pasting in custom geo data.
An example entry of GeoJSON data looks like:
In this example we've referenced GeoJSON via a URL. GeoJSON is a great format for storing spacial data as it's easy to author, read and consume by National Map. Geo data can either be referenced via URL, pasted directly into the Data field, or by referencing the "Share URL" provided by NationalMap when adding data via its UI.
Once you've added a few entries, simple save the form and the resulting page will show a National Map of all your geo data.
Nomenclature
NationalMap introduces the concept of Catalogs and Catalog Items, which we adhere to closely.
Catalog
A catalog can be thought of as a layer except it contains multiple catalog items within it, each with their own data source. A catalog has 2 important properties:
- Name - What will be displayed in the sidebar for the "layer"
- Open - Whether the layer's geo data should be hidden or seen on the map
Catalog Item
A catalog can have many catalog items, but usually will have just one. The catalog item is where the magic happens and has a few key properties:
- name - In most cases will match the name of the catalog
- type - Data type such as "geojson" or "csv"
- url - URL to the geo data of the same data type specified by "Type"
- zoom - The map will zoom in to the bounding box around the data with this option checked
Our Technical Implementation
The software behind NationalMap is called Terria.js, and is open source. We can embed a national map and populate it with geo data via its API. Our implementation is as follows:
Step 1 - Process geo data
From the user supplied form data we generate JSON suitable for consumption by Terria.js/NationalMap. In GovCMS it is not possible to add new code via custom modules, however it's possible to add server side logic via the theme layer. We can use the template_preprocess_paragraph()
hook to generate JSON for consumption by the front end.
In the template_preprocess_paragraph()
hook we check that the entity type is a paragraph
and that the entity bundle is a national_map
. We then generate an array of catalog data. The last but most important part is to pass that data to the client side with:
$vars['#attached']['drupalSettings']['national_map'][$id] = [
'id' => $id,
'catalogs' => $catalogs,
];
Now the JSON can be accessed on the client side via drupalSettings.national_map
with a Drupal behaviour.
Step 2 - Embed map
Embed NationalMap via an iframe:
<iframe id="map" src="https://nationalmap.gov.au" width="100%" height="500px"></iframe>
Step 3 - Wait for map to load
Get the iframe and wait for it to load via Javascript:
// Wait for message event.
window.addEventListener('message', function(event) {
// Get iframe's content window.
var iframe = $('iframe#map').get(0).contentWindow;
// When iframe has loaded.
if (event.source === iframe && event.data === 'ready') {
// Step 3...
}
}
Step 4 - Render geo data
The iframe was introduced in 1997. HTML has come a long way since then and now lets us communicate through the iframe to the embedded website via HTML5's postMessage method:
// Ask iframe to render catalogs.
iframe.postMessage({
initSources: [{
catalog: []
}]
}, 'https://nationalmap.gov.au');
The catalog property takes an array of catalog objects. An example data set looks like this:
[{
type: "group",
name: "Ballarat Recreation",
items: [{
type: "geojson",
name: "Ballarat Bike Racks",
url: "https://data.gov.au/dataset/a75255ab-6a92-4a82-9fdd-dc87b1dce993/resource/9cc717db-1378-4e91-95f3-b39e55b3069d/download/ballaratbikeracks.geojson",
zoomOnEnable: false
},
{
type: "geojson",
name: "Ballarat BBQ's",
url: "https://data.gov.au/dataset/f2ab58d7-18b7-44dc-9121-9cd0ae829d22/resource/b0480515-e45e-419e-a1a6-9a1f862a8751/download/ballaratbbqs.geojson",
zoomOnEnable: true
}
]
}]
The NationalMap Component generates all of this HTML and JSON for you, so you don't have to play around with JSON data structures each time you'd like to embed a national map.
Summary
Convivial's NationalMap Component lets you embed a NationalMap using data from a variety of sources anywhere on a page in a straight forward manner.
An example of the NationalMap embed can be seen on the Convivial Demo page.