Leaflet and GeoDjango Exploration
This section explores direct use of the leaflet.js API. The examples on this page are taken from a combination
of the tutorials on the leaflet.js website and from a presentation at DjangoCon (see the powerpoint in the github).
Leaflet.js can be found at: https://leafletjs.com/
Example htmx and leaflet demo: https://github.com/andywar65/map_swap_example
Basic Usage
In this example we set up a map with an OpenStreetMap base and present a country (Multi-polygon)
in a layer group. The map is centered according to the bounds of the geometry.
In this example we use htmx to cal the back end and replace the button html with a partial. The "HX-Trigger-After-Settle"
header is attached to the response which triggers the javascript fucntion (initMap1()) to initialise the map. The details
of the partial are included in the code block below. We use the geojson plugin to serialise the geometry
into a form that is suitable for leaflet.js.
This is relatively straightforward and does not require too much js.
#template partial
{% load geojson_tags %}
<div id="map1" class="lmap container"></div>
<script id="geodata_map1" type="application/json"
>{{ country|geojsonfeature|safe }}</script>
# javascript
document.body.addEventListener("initMap1", function(evt){
// get the passed in spatial data
collection = JSON.parse(document.getElementById("geodata_map1").textContent);
// create basic map
const map = L.map('map1',{center: [52.00, 0.00], zoom: 10});
// set base_map and add to map
const base_map = L.tileLayer(
"https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
attribution: 'Map data © <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>
contributors',
maxZoom: 19,
}).addTo(map);
// create a layer and add features to layer
const layerGroup = L.layerGroup().addTo(map);
for (feature of collection.features) {
L.geoJson(feature).addTo(layerGroup);
}
// set map view to bounds of the features
if (collection.features.length !== 0) {
map.fitBounds(L.geoJson(collection).getBounds(), {padding: [30,30]});
} else {
map.setView([52,0], 2)
}
})
Pop-ups and markers
In this example markers are placed on the map. We loop through these features extracting the fields a building html for display in the popup.
#template partial
{% load geojson_tags %}
<div id="map2" class="lmap container"></div>
<script id="geodata_map2" type="application/json"
>{{ venues|geojsonfeature:"name,capacity:geom"|safe }}</script>
// event listener Javascript
document.body.addEventListener("initMap2", function(evt){
// loop to bind popup content
function onEachFeature(feature, layer) {
if (feature.properties && feature.properties.name) {
layer.bindPopup(
`<strong>Name:</strong> ${feature.properties.name}<br> <strong>Capacity:</strong> ${feature.properties.capacity}`
, {minWidth: 150});
}
}
// get the passed in spatial data
collection = JSON.parse(document.getElementById("geodata_map2").textContent);
console.log(collection);
// create basic map
const map = L.map('map2',{center: [52.00, 0.00], zoom: 10});
// set base_map and add to map
const base_map = L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
attribution: 'Map data © <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
maxZoom: 19,
}).addTo(map);
const layerGroup = L.layerGroup().addTo(map);
for (marker of collection.features) {
L.geoJson(marker, {onEachFeature: onEachFeature}).addTo(layerGroup);
}
// fit to bounds
if (collection.features.length !== 0) {
map.fitBounds(L.geoJson(collection).getBounds(), {padding: [30,30]});
} else {
map.setView([0,0], 2)
}
})