Chandler Swift
6d81afb395
This doesn't really do all that great a job; Leaflet doesn't really seem to be equipped to do this well (or, more likely, I'm just not figuring out how to do it!). The hack with the extra container is necessary because the transform on the `.leaflet-map-pane` element creates a new stacking context, which messes up even `position: fixed`. I wasn't able to figure out a way to get around this. Written on an airplane without an internet connection, so per the XKCD I'd link but can't, "my apparent IQ goes down like 30 points when [I don't have docs handy; orig "Wikipedia is down"]"!
138 lines
4.9 KiB
HTML
138 lines
4.9 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Lawrence Deer Club Maps</title>
|
|
<link rel="stylesheet" href="/leaflet/leaflet.css" />
|
|
<script src="/leaflet/leaflet.js"></script>
|
|
<style>
|
|
html, body {
|
|
margin: 0;
|
|
padding: 0;
|
|
}
|
|
#map {
|
|
height: 100vh;
|
|
width: 100vw;
|
|
}
|
|
|
|
div.popup dt {
|
|
font-weight: bold;
|
|
}
|
|
|
|
.label {
|
|
font-weight: bold;
|
|
text-align: center;
|
|
margin-top: -1em;
|
|
}
|
|
.label div {
|
|
position: relative;
|
|
left: -50%;
|
|
top: 10px;
|
|
text-shadow: 0 0 2px white;
|
|
}
|
|
.leaflet-popup-content-wrapper {
|
|
height: min(800px, 60vh);
|
|
overflow-y: auto;
|
|
}
|
|
#popupcontainer {
|
|
position: relative;
|
|
z-index: 1000;
|
|
}
|
|
#popupcontainer .leaflet-popup-content-wrapper {
|
|
height: unset;
|
|
}
|
|
#popupcontainer .leaflet-popup {
|
|
transform: none !important;
|
|
position: fixed;
|
|
width: 100vw;
|
|
height: 100vh;
|
|
right: 0;
|
|
left: 0 !important;
|
|
top: 1em;
|
|
bottom: 1em !important;
|
|
overflow: auto;
|
|
}
|
|
#popupcontainer .leaflet-popup-content {
|
|
width: initial;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div id="map"></div>
|
|
<div id="popupcontainer" class="leaflet-container"></div>
|
|
<script>
|
|
(async function() {
|
|
const map = L.map('map').setView([94.505, -0.09], 13);
|
|
// L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
|
// maxZoom: 19,
|
|
// attribution: '© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
|
|
// }).addTo(map);
|
|
|
|
// Make these requests in parallel
|
|
const track_req_promise = fetch('data/track.geojson');
|
|
const plats_req_promise = fetch('data/plats.geojson');
|
|
const data_req_promise = fetch('data/data.json');
|
|
const track_req = await track_req_promise;
|
|
const plats_req = await plats_req_promise;
|
|
const data_req = await data_req_promise;
|
|
const track = await track_req.json();
|
|
const plats = await plats_req.json();
|
|
const data = await data_req.json();
|
|
|
|
L.geoJSON(track).addTo(map);
|
|
|
|
L.geoJSON(plats, {
|
|
filter: feature => !feature.properties.TAO_NAME.toLowerCase().includes("lawrence deer club"),
|
|
onEachFeature: function(feature, layer) {
|
|
const latLngs = layer.getLatLngs()[0];
|
|
const centerish = [ // TODO: actual centroid
|
|
latLngs.reduce((acc, i) => acc + i.lat, 0) / latLngs.length,
|
|
latLngs.reduce((acc, i) => acc + i.lng, 0) / latLngs.length,
|
|
];
|
|
|
|
const label = L.marker(centerish, {
|
|
icon: L.divIcon({
|
|
iconSize: null,
|
|
className: "label",
|
|
html: "<div>" + feature.properties.TAO_NAME + "</div>"
|
|
})
|
|
}).addTo(map);
|
|
},
|
|
}).addTo(map);
|
|
|
|
for (let stand of data.stands) {
|
|
if (stand.location) {
|
|
const marker = L.marker(stand.location).addTo(map);
|
|
const popupContentWrapper = document.createElement('div');
|
|
popupContentWrapper.classList.add('popup');
|
|
let attributesString = '<dl>';
|
|
for (let [attribute, value] of Object.entries(stand.attributes)) {
|
|
attributesString += `<dt>${attribute}</dt><dd>${value}</dd>`;
|
|
}
|
|
attributesString += '</dl>';
|
|
popupContentWrapper.innerHTML = `
|
|
<h2>${stand.name}</h2>
|
|
<img style="width: min(80vw, 300px);" src="images/${stand.image}">
|
|
${attributesString}
|
|
`;
|
|
let popupOptions = {};
|
|
// TODO: evaluate this when creating popup instead of at
|
|
// page instantiation time -- if the page is resized, this
|
|
// won't keep up with those changes.
|
|
if (window.visualViewport.width < 600) {
|
|
popupOptions.pane = document.getElementById('popupcontainer');
|
|
}
|
|
marker.bindPopup(popupContentWrapper, popupOptions);
|
|
}
|
|
}
|
|
|
|
map.fitBounds([
|
|
[47.4865,-93.4068],
|
|
[47.4992,-93.3746],
|
|
]);
|
|
})();
|
|
</script>
|
|
</body>
|
|
</html>
|