diff --git a/InitUiElements.ts b/InitUiElements.ts index c2a2808..180fd06 100644 --- a/InitUiElements.ts +++ b/InitUiElements.ts @@ -436,27 +436,14 @@ export class InitUiElements { editWithJosm = `edit here` } - return new Combine([mapComplete, reportBug, " | ", stats, " | ",editHere, editWithJosm]).Render(); + return new Combine([mapComplete, reportBug, " | ", stats, " | ", editHere, editWithJosm]).Render(); }, [State.state.osmConnection.userDetails]) - ) + ) ); State.state.bm = bm; State.state.layerUpdater = new LayerUpdater(State.state); - /* const queryParam = QueryParameters.GetQueryParameter("background", State.state.layoutToUse.data.defaultBackground); - const queryParamMapped: UIEventSource<{ id: string, name: string, layer: any }> = - queryParam.map<{ id: string, name: string, layer: any }>((id) => { - for (const layer of BaseLayers.baseLayers) { - if (layer.id === id) { - return layer; - } - } - return undefined; - }, [], (layerInfo) => { - return layerInfo.id - }); - - queryParamMapped.syncWith(bm.CurrentLayer);*/ + } diff --git a/Logic/AvailableBaseLayers.ts b/Logic/AvailableBaseLayers.ts index b3d9343..a8a4fa6 100644 --- a/Logic/AvailableBaseLayers.ts +++ b/Logic/AvailableBaseLayers.ts @@ -3,23 +3,38 @@ import {UIEventSource} from "./UIEventSource"; import {GeoOperations} from "./GeoOperations"; import {State} from "../State"; import {Basemap} from "./Leaflet/Basemap"; +import {QueryParameters} from "./Web/QueryParameters"; + +export interface BaseLayer { + id: string, + name: string, + attribution_url: string, + layer: any, + max_zoom: number, + min_zoom: number; + feature: any +} /** * Calculates which layers are available at the current location */ export default class AvailableBaseLayers { - public static osmCarto = + public static osmCarto: BaseLayer = { - id: "osm", url: "https://tile.openstreetmap.org/{z}/{x}/{y}.png", - max_zoom: 19, license_url: "https://openStreetMap.org/copyright", - name: "OpenStreetMap", geometry: null, - leafletLayer: Basemap.CreateBackgroundLayer("osm", "OpenStreetMap", - "https://tile.openstreetmap.org/{z}/{x}/{y}.png", "OpenStreetMap", 19, false, false) + id: "osm", + //max_zoom: 19, + attribution_url: "https://openStreetMap.org/copyright", + name: "OpenStreetMap", + layer: Basemap.CreateBackgroundLayer("osm", "OpenStreetMap", + "https://tile.openstreetmap.org/{z}/{x}/{y}.png", "OpenStreetMap", 19, false, false), + feature: null, + max_zoom: 19, + min_zoom: 0 } public static layerOverview = AvailableBaseLayers.LoadRasterIndex(); - public availableEditorLayers: UIEventSource<{ id: string, url: string, max_zoom: number, license_url: string, name: string, geometry: any, leafletLayer: any }[]>; + public availableEditorLayers: UIEventSource; constructor(state: State) { const self = this; @@ -41,13 +56,54 @@ export default class AvailableBaseLayers { } } - return currentLocation; + return currentLayers; }); + + this.availableEditorLayers.addCallbackAndRun(availableLayers => { + const layerControl = (state.bm as Basemap).CurrentLayer; + const currentLayer = layerControl.data.id; + for (const availableLayer of availableLayers) { + if (availableLayer.id === currentLayer) { + + if (availableLayer.max_zoom < state.locationControl.data.zoom) { + break; + } + + if (availableLayer.min_zoom > state.locationControl.data.zoom) { + break; + } + + + return; // All good! + } + } + // Oops, we panned out of range for this layer! + console.log("AvailableBaseLayers-actor: detected that the current bounds aren't sufficient anymore - reverting to OSM standard") + layerControl.setData(AvailableBaseLayers.osmCarto.layer); + + }); + + + const queryParam = QueryParameters.GetQueryParameter("background", State.state.layoutToUse.data.defaultBackground); + + queryParam.addCallbackAndRun(selectedId => { + console.log("Selected layer is ", selectedId) + const available = self.availableEditorLayers.data; + for (const layer of available) { + if (layer.id === selectedId) { + state.bm.CurrentLayer.setData(layer.layer); + } + } + }) + + state.bm.CurrentLayer.addCallbackAndRun(currentLayer => { + queryParam.setData(currentLayer.id); + }); + } - public static AvailableLayersAt(lon: number, lat: number): - { url: string, max_zoom: number, license_url: string, name: string, geometry: any }[] { + public static AvailableLayersAt(lon: number, lat: number): BaseLayer[] { const availableLayers = [AvailableBaseLayers.osmCarto as any] const globalLayers = []; for (const i in AvailableBaseLayers.layerOverview) { @@ -69,24 +125,27 @@ export default class AvailableBaseLayers { return availableLayers.concat(globalLayers); } - private static LoadRasterIndex(): { id: string, url: string, max_zoom: number, license_url: string, name: string, feature: any }[] { - const layers: { id: string, url: string, max_zoom: number, license_url: string, name: string, feature: any, leafletLayer: any }[] = [] + private static LoadRasterIndex(): BaseLayer[] { + const layers: BaseLayer[] = [] // @ts-ignore const features = editorlayerindex.features; for (const i in features) { const layer = features[i]; const props = layer.properties; - if(props.id === "Bing"){ + if (props.id === "Bing") { // Doesnt work continue; } - - if (props.overlay) { + + if (props.id === "carto") { + // Already added by default continue; } - - if(props.max_zoom < 19){ + + if (props.overlay) { + console.log("Refusing overlay layer ", props.name) + continue; } @@ -95,11 +154,12 @@ export default class AvailableBaseLayers { } if (props.url.toLowerCase().indexOf("{bbox}") > 0) { + console.warn("Editor layer index: needs bbox ", props) continue; } if(props.name === undefined){ - console.log("Editor layer index: name not defined on ", props) + console.warn("Editor layer index: name not defined on ", props) continue } @@ -116,12 +176,12 @@ export default class AvailableBaseLayers { // Note: if layer.geometry is null, there is global coverage for this layer layers.push({ id: props.id, - feature: layer, - url: props.url, - max_zoom: props.max_zoom, - license_url: props.license_url, + max_zoom: props.max_zoom ?? 25, + min_zoom: props.min_zoom ?? 1, + attribution_url: props.license_url, name: props.name, - leafletLayer: leafletLayer + layer: leafletLayer, + feature: layer }); } return layers; diff --git a/Logic/Leaflet/Basemap.ts b/Logic/Leaflet/Basemap.ts index f49dab6..5158e99 100644 --- a/Logic/Leaflet/Basemap.ts +++ b/Logic/Leaflet/Basemap.ts @@ -124,11 +124,19 @@ export class Basemap { maxZoom: number, isWms: boolean, isWMTS?: boolean) { url = url.replace("{zoom}", "{z}") - .replace("{switch:", "{") .replace("{proj}", "EPSG:3857") .replace("{width}", "256") .replace("{height}", "256") + const subdomainsMatch = url.match(/{switch:[^}]*}/) + let domains : string[] = []; + if (subdomainsMatch !== null) { + let domainsStr = subdomainsMatch[0].substr("{switch:".length); + domainsStr = domainsStr.substr(0, domainsStr.length-1); + domains = domainsStr.split(","); + url = url.replace(/{switch:[^}]*}/, "{s}") + } + //geoservices.informatievlaanderen.be/raadpleegdiensten/dhmv/wms?FORMAT=image/jpeg&VERSION=1.1.1&SERVICE=WMS&REQUEST=GetMap&LAYERS=DHMV_II_SVF_25cm&STYLES=&SRS=EPSG:3857&WIDTH=256&HEIGHT=256 if (isWms) { return { @@ -137,7 +145,8 @@ export class Basemap { layer: L.tileLayer.wms(url, { maxZoom: maxZoom ?? 19, - attribution: attribution + " | " + attribution: attribution + " | ", + subdomains: domains }) } } @@ -150,7 +159,8 @@ export class Basemap { attribution: attribution, maxZoom: maxZoom, minZoom: 1, - wmts: isWMTS ?? false + wmts: isWMTS ?? false, + subdomains: domains }) } } diff --git a/UI/BackgroundSelector.ts b/UI/BackgroundSelector.ts index 3955596..0d4ff55 100644 --- a/UI/BackgroundSelector.ts +++ b/UI/BackgroundSelector.ts @@ -1,10 +1,9 @@ import {UIElement} from "./UIElement"; -import AvailableBaseLayers from "../Logic/AvailableBaseLayers"; +import AvailableBaseLayers, {BaseLayer} from "../Logic/AvailableBaseLayers"; import {DropDown} from "./Input/DropDown"; import Translations from "./i18n/Translations"; import {State} from "../State"; import {UIEventSource} from "../Logic/UIEventSource"; -import Combine from "./Base/Combine"; export default class BackgroundSelector extends UIElement { @@ -23,20 +22,16 @@ export default class BackgroundSelector extends UIElement { private CreateDropDown(available) { if(available.length === 0){ - console.warn("NO LAYERS FOUND!") return; } - const baseLayers: { value: any, shown: string }[] = []; + const baseLayers: { value: BaseLayer, shown: string }[] = []; for (const i in available) { - const layer: { url: string, max_zoom: number, license_url: number, name: string, geometry: any, leafletLayer: any } = available[i]; - baseLayers.push({value: layer.leafletLayer, shown: layer.name}); - + const layer: BaseLayer = available[i]; + baseLayers.push({value: layer.layer, shown: layer.name ?? "id:" + layer.id}); } - const dropdown = new DropDown(Translations.t.general.backgroundMap, baseLayers, State.state.bm.CurrentLayer) - console.log("Installed dropdown with ",baseLayers); - this._dropdown = dropdown; + this._dropdown = new DropDown(Translations.t.general.backgroundMap, baseLayers, State.state.bm.CurrentLayer); } InnerRender(): string { diff --git a/clean.sh b/clean.sh index e7d32bd..8736264 100755 --- a/clean.sh +++ b/clean.sh @@ -24,3 +24,5 @@ for f in ./*.html; do rm $f fi done + +rm -rf .cache \ No newline at end of file