Last week I shared my initial experiences with Leaflet and I thought I'd share a small demo I built with it - a general purpose GeoJSON viewer.
GeoJSON and Leaflet
As I mentioned at the end of my last post, GeoJSON is a specification for encoding ad hoc geographic data. Here's an example:
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"id": 0,
"properties": {
"Code": "FRLA",
"Name": "Frederick Law Olmsted National Historic Site"
},
"geometry": {
"type": "Point",
"coordinates": [
-71.13112956925647,
42.32550867371509
]
}
},
{
"type": "Feature",
"id": 1,
"properties": {
"Code": "GLDE",
"Name": "Gloria Dei Church National Historic Site"
},
"geometry": {
"type": "Point",
"coordinates": [
-75.14358360598474,
39.93437740957208
]
}
},
]
}
GeoJSON can encode points, lines, polygons, and more, and support a properties
section that can have anything in it. Leaflet makes it easy to use GeoJSON. Here's the example I used in that last post:
let dataReq = await fetch('https://assets.codepen.io/74045/national-parks.geojson');
let data = await dataReq.json();
L.geoJSON(data).bindPopup(function (layer) {
return layer.feature.properties.Name;
}).addTo(map);
That's literally it. Given how easy this, I thought I'd build a demo where the data was provided by the user.
The Application
My application is built with simple vanilla JavaScript, no Alpine even, and lets you drop a file into the browser to load the information.
My code waits for DOMContentLoaded
and then registers event handlers for dragdrop support:
document.addEventListener('dragover', e => e.preventDefault());
document.addEventListener('drop', handleDrop);
When you drop a file, I then use a bit of code to read it in.
function handleDrop(e) {
e.preventDefault();
let droppedFiles = e.dataTransfer.files;
if(!droppedFiles) return;
let myFile = droppedFiles[0];
let ext = myFile.name.split('.').pop();
if(ext !== 'geojson') {
alert('Drag/drop a .geojson file only.');
return;
}
let reader = new FileReader();
reader.onload = e => {
loadGeoJSON(JSON.parse(e.target.result));
};
updateStatus('Reading .geojson');
reader.readAsText(myFile);
}
The loadGeoJSON
function handles adding the data to Leaflet:
async function loadGeoJSON(data) {
updateStatus(`.geojson loaded with ${data.features.length} features. Adding to map now.`);
L.geoJSON(data, {
}).bindPopup(function (layer) {
return `
<p>
<b>Properties:</b><br>
<pre style='white-space:pre-wrap'><code>
${JSON.stringify(layer.feature.properties,null,' ')}
</code></pre>
</p>
`;
},{minWidth:450}).addTo(map);
}
This is pretty much the same code as before, except that my popup uses a basic dump (stringify
) of the properties
key. Note that this will not work for all files, especially if there's a lot of data there. I could get fancier with my output there and perhaps add a max height with overflow. That being said, here is how it looks after adding America's parks to it (and clicking one feature):
You can test it out here (full screen): https://codepen.io/cfjedimaster/full/GRbxVVR
And here's the full code:
See the Pen Leaflet geojson viewer (v2) by Raymond Camden (@cfjedimaster) on CodePen.