diff --git a/dve.js b/dve.js index c9a1741..936bbcb 100644 --- a/dve.js +++ b/dve.js @@ -28,7 +28,14 @@ function fillDropdown(select) { } } -function readUrlPosition() { +function readUrlState() { + const state = { + center, + zoom, + count: 2, + layers: [] + }; + const match = window.location.hash.match(/^#map=([0-9.]+)\/(-?[0-9.]+)\/(-?[0-9.]+)/); if (match) { @@ -37,25 +44,52 @@ function readUrlPosition() { const lng = parseFloat(match[3]); if (Number.isFinite(lat) && Number.isFinite(lng) && Number.isFinite(z)) { - return { - center: [lat, lng], - zoom: z - }; + state.center = [lat, lng]; + state.zoom = z; } } - return { - center, - zoom - }; + const params = new URLSearchParams(window.location.hash.replace(/^#map=[^&]*/, "")); + const count = parseInt(params.get("count"), 10); + + if (mapCounts.includes(count)) { + state.count = count; + } + + for (let i = 1; i <= state.count; i++) { + const layer = params.get("layer" + i); + + if (layer) state.layers.push(layer); + } + + return state; } -function writeUrlPosition(map) { +function getSelectedLayers(count) { + const selected = []; + + for (let i = 1; i <= count; i++) { + const select = document.getElementById("select" + i); + if (select && select.value) selected.push(select.value); + } + + return selected; +} + +function writeUrlState(map) { if (urlUpdateTimer) clearTimeout(urlUpdateTimer); urlUpdateTimer = setTimeout(() => { const c = map.getCenter(); - const hash = "#map=" + map.getZoom() + "/" + c.lat.toFixed(5) + "/" + c.lng.toFixed(5); + const count = parseInt(document.getElementById("mapCountSelector").value, 10); + let hash = "#map=" + map.getZoom() + "/" + c.lat.toFixed(5) + "/" + c.lng.toFixed(5); + + hash += "&count=" + count; + + const selected = getSelectedLayers(count); + selected.forEach((name, index) => { + hash += "&layer" + (index + 1) + "=" + encodeURIComponent(name); + }); history.replaceState(null, "", hash); }, 100); @@ -71,7 +105,7 @@ function sync(source) { }); syncing = false; - writeUrlPosition(source); + writeUrlState(source); updateCrosshairs(); } @@ -194,7 +228,7 @@ function initCrosshair(map) { } function init() { - const urlPosition = readUrlPosition(); + const urlState = readUrlState(); const mapCountSelector = document.getElementById("mapCountSelector"); fillMapCountDropdown(mapCountSelector); @@ -202,7 +236,11 @@ function init() { const select = document.getElementById("select" + i); fillDropdown(select); - const map = L.map("map" + i, { center: urlPosition.center, zoom: urlPosition.zoom, zoomControl: false }); + if (urlState.layers[i - 1] && TILE_SERVERS[urlState.layers[i - 1]]) { + select.value = urlState.layers[i - 1]; + } + + const map = L.map("map" + i, { center: urlState.center, zoom: urlState.zoom, zoomControl: false }); map.on("move", () => sync(map)); map.on("zoom", () => sync(map)); @@ -218,15 +256,18 @@ function init() { select.addEventListener("change", e => { const key = e.target.value; layers[i - 1] = setLayer(map, TILE_SERVERS[key], layers[i - 1]); + writeUrlState(map); }); } - mapCountSelector.value = "2"; + mapCountSelector.value = urlState.count; mapCountSelector.addEventListener("change", e => { setMapCount(parseInt(e.target.value, 10)); + writeUrlState(maps[0]); }); setMapCount(parseInt(mapCountSelector.value, 10)); + writeUrlState(maps[0]); } async function loadTileConfigs(json_files) {