Add Azure Maps road and satellite layers

This commit is contained in:
livio committed 2026-09-11 19:53:28 +02:00
1 parent 3ea51a6842
commit 9733137fdd
6 files changed
+266 -4

No files matched your search

+132 -1
View File
@@ -2,6 +2,7 @@ const lmeState = {
map: null,
baseLayers: {},
currentBase: null,
currentBaseName: "satellite",
cadastre: null,
cadastreLayers: ["CP.CadastralParcel", "codice_plla", "CP.CadastralZoning", "fabbricati"],
cadastreOpacity: 0.75,
@@ -19,7 +20,9 @@ const lmeState = {
lastPosition: null,
fileImportBound: false,
resizeBound: false,
googleMapsLoading: null
googleMapsLoading: null,
azureMapsKey: null,
azureAttribution: null
};
window.lmeMap = {
@@ -36,6 +39,8 @@ window.lmeMap = {
loadWorkspace,
setBaseLayer,
configureGoogleMaps,
configureAzureMaps,
clearAzureMaps,
setCadastreOpacity,
toggleCadastreLayer,
startGps,
@@ -117,6 +122,7 @@ function init() {
L.popup().setLatLng(event.latlng).setContent(info).openOn(lmeState.map);
}
});
lmeState.map.on("moveend", () => void updateAzureAttribution());
setInfo("Mappa pronta: satellite + catasto AdE");
}
@@ -384,6 +390,7 @@ function setBaseLayer(name) {
lmeState.map.removeLayer(lmeState.currentBase);
}
lmeState.currentBase = selected.addTo(lmeState.map);
lmeState.currentBaseName = selected === lmeState.baseLayers[name] ? name : "satellite";
lmeState.currentBase.bringToBack();
const labels = {
satellite: "Satellite Esri",
@@ -392,10 +399,17 @@ function setBaseLayer(name) {
topographic: "Topografica Esri",
terrain: "OpenTopoMap",
carto: "CARTO Voyager",
"azure-road": "Strade Azure Maps",
"azure-satellite": "Satellite Azure Maps",
"google-satellite": "Satellite Google Maps",
"google-roadmap": "Strade Google Maps"
};
setInfo(`Sfondo attivo: ${labels[name] || labels.satellite}. Il catasto AdE resta sovrapposto.`);
if (lmeState.currentBaseName.startsWith("azure-")) {
void updateAzureAttribution();
} else {
clearAzureAttribution();
}
}
function configureGoogleMaps(apiKey) {
@@ -443,6 +457,123 @@ function createGoogleLayers() {
lmeState.baseLayers["google-roadmap"] ||= L.gridLayer.googleMutant({ type: "roadmap", maxZoom: 22 });
}
function configureAzureMaps(subscriptionKey) {
const key = (subscriptionKey || "").trim();
if (!key) {
throw new Error("Chiave Azure Maps mancante.");
}
if (lmeState.azureMapsKey === key
&& lmeState.baseLayers["azure-road"]
&& lmeState.baseLayers["azure-satellite"]) {
return;
}
const activeAzureLayer = lmeState.currentBaseName.startsWith("azure-")
? lmeState.currentBaseName
: null;
if (activeAzureLayer && lmeState.currentBase) {
lmeState.map.removeLayer(lmeState.currentBase);
}
lmeState.azureMapsKey = key;
lmeState.baseLayers["azure-road"] = createAzureLayer(key, "microsoft.base.road", 22);
lmeState.baseLayers["azure-satellite"] = createAzureLayer(key, "microsoft.imagery", 19);
if (activeAzureLayer) {
lmeState.currentBase = lmeState.baseLayers[activeAzureLayer].addTo(lmeState.map);
lmeState.currentBase.bringToBack();
void updateAzureAttribution();
}
}
function clearAzureMaps() {
if (lmeState.currentBaseName.startsWith("azure-") && lmeState.currentBase) {
lmeState.map.removeLayer(lmeState.currentBase);
lmeState.currentBase = lmeState.baseLayers.satellite.addTo(lmeState.map);
lmeState.currentBase.bringToBack();
lmeState.currentBaseName = "satellite";
}
delete lmeState.baseLayers["azure-road"];
delete lmeState.baseLayers["azure-satellite"];
lmeState.azureMapsKey = null;
clearAzureAttribution();
}
function createAzureLayer(key, tilesetId, maxNativeZoom) {
const url = `https://atlas.microsoft.com/map/tile?api-version=2024-04-01&tilesetId=${tilesetId}&zoom={z}&x={x}&y={y}&tileSize=256&language=it-IT&view=Auto&subscription-key=${encodeURIComponent(key)}`;
const layer = L.tileLayer(url, {
minZoom: tilesetId === "microsoft.imagery" ? 1 : 0,
maxNativeZoom,
maxZoom: 22,
attribution: "Microsoft Azure Maps"
});
let errorShown = false;
layer.on("tileerror", () => {
if (!errorShown) {
errorShown = true;
setInfo("Azure Maps non ha restituito le tessere. Controlla quota e permessi Render della chiave.");
}
});
return layer;
}
async function updateAzureAttribution() {
if (!lmeState.azureMapsKey || !lmeState.currentBaseName.startsWith("azure-")) {
return;
}
const requestedLayer = lmeState.currentBaseName;
const tilesetId = requestedLayer === "azure-satellite" ? "microsoft.imagery" : "microsoft.base.road";
const bounds = lmeState.map.getBounds();
const zoom = Math.min(lmeState.map.getZoom(), tilesetId === "microsoft.imagery" ? 19 : 22);
const bbox = [bounds.getWest(), bounds.getSouth(), bounds.getEast(), bounds.getNorth()].join(",");
const url = `https://atlas.microsoft.com/map/attribution?api-version=2024-04-01&tilesetId=${tilesetId}&zoom=${zoom}&bounds=${bbox}`;
try {
const response = await fetch(url, {
headers: {
Accept: "application/json",
"subscription-key": lmeState.azureMapsKey
}
});
if (!response.ok) {
return;
}
const payload = await response.json();
if (lmeState.currentBaseName !== requestedLayer) {
return;
}
const attribution = [...new Set((payload.copyrights || []).map(htmlToText).filter(Boolean))].join(" | ");
setAzureAttribution(attribution);
} catch {
clearAzureAttribution();
}
}
function setAzureAttribution(text) {
clearAzureAttribution();
if (!text) {
return;
}
lmeState.azureAttribution = escapeHtml(text);
lmeState.map.attributionControl.addAttribution(lmeState.azureAttribution);
}
function clearAzureAttribution() {
if (lmeState.azureAttribution) {
lmeState.map.attributionControl.removeAttribution(lmeState.azureAttribution);
lmeState.azureAttribution = null;
}
}
function htmlToText(value) {
const element = document.createElement("div");
element.innerHTML = String(value || "");
return element.textContent?.trim() || "";
}
function setCadastreOpacity(value) {
lmeState.cadastreOpacity = Number(value || 0.75);
if (lmeState.cadastre) {