Files
MeshTender/internal/web/static/meshmap.js
T
2026-07-01 19:31:09 -04:00

69 lines
2.6 KiB
JavaScript

// meshBaseLayers adds the dark (default) and a light basemap to a map, with a
// layers control to toggle between them. The choice is remembered in localStorage
// so it carries across maps and pages. Dark matches the UI; the light layer (CARTO
// Voyager) reads better in bright conditions and for some eyes. The control is
// left expanded — Leaflet's collapsed toggle needs an icon asset we don't bundle.
function meshBaseLayers(map) {
var attribution = "© OpenStreetMap © CARTO";
var dark = L.tileLayer("https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png", {
maxZoom: 19,
subdomains: "abcd",
attribution: attribution,
});
var light = L.tileLayer("https://{s}.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}{r}.png", {
maxZoom: 19,
subdomains: "abcd",
attribution: attribution,
});
var pref = null;
try {
pref = localStorage.getItem("mt_map_base");
} catch (e) {
/* storage unavailable (private mode); fall back to dark */
}
(pref === "light" ? light : dark).addTo(map);
L.control.layers({ Dark: dark, Light: light }, null, { position: "topright", collapsed: false }).addTo(map);
map.on("baselayerchange", function (e) {
try {
localStorage.setItem("mt_map_base", e.name === "Light" ? "light" : "dark");
} catch (e) {
/* ignore */
}
});
}
// meshMap renders a dark-mode Leaflet map of points into the element with the
// given id. pts is an array of {name, lat, lon}. Does nothing if pts is empty.
function meshMap(elId, pts) {
if (!pts || !pts.length) return;
// Turn off every Leaflet animation so the map paints once, in its final
// position, with no flash on load: zoomAnimation (zoom transitions),
// fadeAnimation (tiles fading in), markerZoomAnimation (markers scaling).
var map = L.map(elId, {
scrollWheelZoom: false,
zoomAnimation: false,
fadeAnimation: false,
markerZoomAnimation: false,
});
meshBaseLayers(map);
var group = L.featureGroup(
pts.map(function (p) {
return L.circleMarker([p.lat, p.lon], {
radius: 7,
color: "#4dabf7",
weight: 2,
fillColor: "#4dabf7",
fillOpacity: 0.6,
}).bindPopup(p.name);
})
).addTo(map);
// Set the view exactly once, non-animated, so the map paints in its final
// position with no fit/zoom flash on load. A lone repeater would otherwise fit
// at max zoom, so give it a fixed neighborhood zoom for context instead.
if (pts.length === 1) {
map.setView([pts[0].lat, pts[0].lon], 15, { animate: false });
} else {
map.fitBounds(group.getBounds().pad(0.3), { animate: false });
}
}