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 That Home button is the top of a small top-left stack — Home, zoom
in/out (`NavigationControl`, `showCompass: false` since this map never in/out (`NavigationControl`, `showCompass: false` since this map never
rotates), locate-me (`GeolocateControl`), and a "Base map" button — rotates), a passive zoom-level readout (`ZoomLevelControl`, a plain div
matching the National Park Service's own map control layout (grouped 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 together on the map itself, rather than split across corners or
between the map and a side panel). The last of those, between the map and a side panel). The last of those,
`MapLayersButton` (`public/js/map.js`), is a second entry point into `MapLayersButton` (`public/js/map.js`), is a second entry point into
+12
View File
@@ -472,6 +472,18 @@ html, body {
word-break: break-word; 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 { .gpx-popup__time {
color: #888; color: #888;
font-size: 12px; 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({ const map = new MaplibreMap({
container: "map", container: "map",
style: ONLINE_STYLE, style: ONLINE_STYLE,
@@ -195,10 +228,10 @@ const map = new MaplibreMap({
hash: "map", hash: "map",
}); });
// A compact top-left stack — Home, zoom, locate-me, base map — matching // A compact top-left stack — Home, zoom, zoom-level readout, locate-me,
// the National Park Service's own map control layout, all grouped // base map — matching the National Park Service's own map control layout,
// together rather than split across corners. Added in this order since // all grouped together rather than split across corners. Added in this
// MapLibre stacks same-position controls in add order. // order since MapLibre stacks same-position controls in add order.
// //
// homePosition/zoom pinned to the app's own default rather than left to the // 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 // 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 // showCompass: false — this map never rotates, so a bearing-reset button
// (NavigationControl's default third button) would just be dead weight. // (NavigationControl's default third button) would just be dead weight.
map.addControl(new NavigationControl({ showCompass: false }), "top-left"); map.addControl(new NavigationControl({ showCompass: false }), "top-left");
map.addControl(new ZoomLevelControl(), "top-left");
map.addControl( map.addControl(
new GeolocateControl({ new GeolocateControl({
positionOptions: { enableHighAccuracy: true }, positionOptions: { enableHighAccuracy: true },