Add a zoom-level readout to the map control stack
CI / check (push) Successful in 49s
CI / deploy (push) Successful in 18s

Matches the small numbered square NPS keeps next to its own zoom
buttons — a passive display, not a button, so it's plain markup with
no click behavior.
This commit is contained in:
randy committed 2026-09-07 22:12:06 +02:00
1 parent 88637ded22
commit 16d36e4441
3 files changed
+55 -6

No files matched your search

+5 -2
View File
@@ -145,8 +145,11 @@ app's default view, not the visitor's own location — that's
That Home button is the top of a small top-left stack — Home, zoom
in/out (`NavigationControl`, `showCompass: false` since this map never
rotates), locate-me (`GeolocateControl`), and a "Base map" button —
matching the National Park Service's own map control layout (grouped
rotates), a passive zoom-level readout (`ZoomLevelControl`, a plain div
updated on the map's `zoom` event — not a button, since it has no
click behavior of its own), locate-me (`GeolocateControl`), and a
"Base map" button — matching the National Park Service's own map
control layout (grouped
together on the map itself, rather than split across corners or
between the map and a side panel). The last of those,
`MapLayersButton` (`public/js/map.js`), is a second entry point into
+12
View File
@@ -472,6 +472,18 @@ html, body {
word-break: break-word;
}
.zoom-level-ctrl__value {
width: 29px;
height: 29px;
display: flex;
align-items: center;
justify-content: center;
font-size: 12px;
font-weight: 600;
color: #333;
user-select: none;
}
.gpx-popup__time {
color: #888;
font-size: 12px;
+38 -4
View File
@@ -182,6 +182,39 @@ class MapLayersButton {
}
}
// A passive zoom-level readout, sitting in the same stack as the buttons
// around it — the National Park Service's own control layout has one (the
// small numbered square next to their zoom buttons). Not a button: no
// click behavior, just a live display, so it's a plain div rather than a
// <button> (no hover/focus affordance implying it does something).
class ZoomLevelControl {
onAdd(map) {
this._map = map;
this._container = document.createElement("div");
this._container.className = "maplibregl-ctrl maplibregl-ctrl-group zoom-level-ctrl";
this._label = document.createElement("div");
this._label.className = "zoom-level-ctrl__value";
this._container.appendChild(this._label);
this._update = () => {
this._label.textContent = Math.round(map.getZoom());
};
this._update();
map.on("zoom", this._update);
return this._container;
}
onRemove() {
this._map.off("zoom", this._update);
this._container.remove();
}
getDefaultPosition() {
return "top-left";
}
}
const map = new MaplibreMap({
container: "map",
style: ONLINE_STYLE,
@@ -195,10 +228,10 @@ const map = new MaplibreMap({
hash: "map",
});
// A compact top-left stack — Home, zoom, locate-me, base map — matching
// the National Park Service's own map control layout, all grouped
// together rather than split across corners. Added in this order since
// MapLibre stacks same-position controls in add order.
// A compact top-left stack — Home, zoom, zoom-level readout, locate-me,
// base map — matching the National Park Service's own map control layout,
// all grouped together rather than split across corners. Added in this
// order since MapLibre stacks same-position controls in add order.
//
// homePosition/zoom pinned to the app's own default rather than left to the
// button's own fallback (current center/zoom at construction) — now that
@@ -211,6 +244,7 @@ map.addControl(new HomeButton({ homePosition: CENTER, zoom: ZOOM }), "top-left")
// showCompass: false — this map never rotates, so a bearing-reset button
// (NavigationControl's default third button) would just be dead weight.
map.addControl(new NavigationControl({ showCompass: false }), "top-left");
map.addControl(new ZoomLevelControl(), "top-left");
map.addControl(
new GeolocateControl({
positionOptions: { enableHighAccuracy: true },