Fix overlay layers
This commit is contained in:
parent
3aeedf22c8
commit
24f7610d0a
15 changed files with 216 additions and 184 deletions
|
@ -29,7 +29,6 @@ export default class FeaturePropertiesStore {
|
|||
|
||||
const source = self._elements.get(id)
|
||||
if (source === undefined) {
|
||||
console.log("Adding feature store for", id)
|
||||
self._elements.set(id, new UIEventSource<any>(feature.properties))
|
||||
continue
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ export interface MapProperties {
|
|||
readonly location: UIEventSource<{ lon: number; lat: number }>
|
||||
readonly zoom: UIEventSource<number>
|
||||
readonly minzoom: UIEventSource<number>
|
||||
readonly maxzoom: UIEventSource<number>
|
||||
readonly bounds: UIEventSource<BBox>
|
||||
readonly rasterLayer: UIEventSource<RasterLayerPolygon | undefined>
|
||||
readonly maxbounds: UIEventSource<undefined | BBox>
|
||||
|
|
|
@ -123,7 +123,9 @@ export interface RasterLayerProperties {
|
|||
/**
|
||||
* The name of the imagery source
|
||||
*/
|
||||
readonly name: string
|
||||
readonly name: string | Record<string, string>
|
||||
|
||||
readonly isOverlay?: boolean
|
||||
|
||||
readonly id: string
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { LayerConfigJson } from "./LayerConfigJson"
|
||||
import TilesourceConfigJson from "./TilesourceConfigJson"
|
||||
import ExtraLinkConfigJson from "./ExtraLinkConfigJson"
|
||||
import { RasterLayerProperties } from "../../RasterLayers"
|
||||
|
||||
/**
|
||||
* Defines the entire theme.
|
||||
|
@ -148,7 +148,7 @@ export interface LayoutConfigJson {
|
|||
/**
|
||||
* Define some (overlay) slippy map tilesources
|
||||
*/
|
||||
tileLayerSources?: TilesourceConfigJson[]
|
||||
tileLayerSources?: (RasterLayerProperties & { defaultState?: true | boolean })[]
|
||||
|
||||
/**
|
||||
* The layers to display.
|
||||
|
|
|
@ -3,11 +3,12 @@ import { LayoutConfigJson } from "./Json/LayoutConfigJson"
|
|||
import LayerConfig from "./LayerConfig"
|
||||
import { LayerConfigJson } from "./Json/LayerConfigJson"
|
||||
import Constants from "../Constants"
|
||||
import TilesourceConfig from "./TilesourceConfig"
|
||||
import { ExtractImages } from "./Conversion/FixImages"
|
||||
import ExtraLinkConfig from "./ExtraLinkConfig"
|
||||
import { Utils } from "../../Utils"
|
||||
import LanguageUtils from "../../Utils/LanguageUtils"
|
||||
import { RasterLayerProperties } from "../RasterLayers"
|
||||
|
||||
/**
|
||||
* Minimal information about a theme
|
||||
**/
|
||||
|
@ -39,7 +40,7 @@ export default class LayoutConfig implements LayoutInformation {
|
|||
public widenFactor: number
|
||||
public defaultBackgroundId?: string
|
||||
public layers: LayerConfig[]
|
||||
public tileLayerSources: TilesourceConfig[]
|
||||
public tileLayerSources: (RasterLayerProperties & { defaultState?: true | boolean })[]
|
||||
public readonly hideFromOverview: boolean
|
||||
public lockLocation: boolean | [[number, number], [number, number]]
|
||||
public readonly enableUserBadge: boolean
|
||||
|
@ -161,9 +162,7 @@ export default class LayoutConfig implements LayoutInformation {
|
|||
this.widenFactor = json.widenFactor ?? 1.5
|
||||
|
||||
this.defaultBackgroundId = json.defaultBackgroundId
|
||||
this.tileLayerSources = (json.tileLayerSources ?? []).map(
|
||||
(config, i) => new TilesourceConfig(config, `${this.id}.tileLayerSources[${i}]`)
|
||||
)
|
||||
this.tileLayerSources = json.tileLayerSources ?? []
|
||||
// At this point, layers should be expanded and validated either by the generateScript or the LegacyJsonConvert
|
||||
this.layers = json.layers.map(
|
||||
(lyrJson) =>
|
||||
|
|
|
@ -1,43 +0,0 @@
|
|||
import TilesourceConfigJson from "./Json/TilesourceConfigJson"
|
||||
import Translations from "../../UI/i18n/Translations"
|
||||
import { Translation } from "../../UI/i18n/Translation"
|
||||
|
||||
export default class TilesourceConfig {
|
||||
public readonly source: string
|
||||
public readonly id: string
|
||||
public readonly isOverlay: boolean
|
||||
public readonly name: Translation
|
||||
public readonly minzoom: number
|
||||
public readonly maxzoom: number
|
||||
public readonly defaultState: boolean
|
||||
|
||||
constructor(config: TilesourceConfigJson, ctx: string = "") {
|
||||
this.id = config.id
|
||||
this.source = config.source
|
||||
this.isOverlay = config.isOverlay ?? false
|
||||
this.name = Translations.T(config.name)
|
||||
this.minzoom = config.minZoom ?? 0
|
||||
this.maxzoom = config.maxZoom ?? 999
|
||||
this.defaultState = config.defaultState ?? true
|
||||
if (this.id === undefined) {
|
||||
throw "An id is obligated"
|
||||
}
|
||||
if (this.minzoom > this.maxzoom) {
|
||||
throw (
|
||||
"Invalid tilesourceConfig: minzoom should be smaller then maxzoom (at " + ctx + ")"
|
||||
)
|
||||
}
|
||||
if (this.minzoom < 0) {
|
||||
throw "minzoom should be > 0 (at " + ctx + ")"
|
||||
}
|
||||
if (this.maxzoom < 0) {
|
||||
throw "maxzoom should be > 0 (at " + ctx + ")"
|
||||
}
|
||||
if (this.source.indexOf("{zoom}") >= 0) {
|
||||
throw "Invalid source url: use {z} instead of {zoom} (at " + ctx + ".source)"
|
||||
}
|
||||
if (!this.defaultState && config.name === undefined) {
|
||||
throw "Disabling an overlay without a name is not possible"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -43,6 +43,7 @@ import MetaTagging from "../Logic/MetaTagging"
|
|||
import ChangeGeometryApplicator from "../Logic/FeatureSource/Sources/ChangeGeometryApplicator"
|
||||
import { NewGeometryFromChangesFeatureSource } from "../Logic/FeatureSource/Sources/NewGeometryFromChangesFeatureSource"
|
||||
import OsmObjectDownloader from "../Logic/Osm/OsmObjectDownloader"
|
||||
import ShowOverlayRasterLayer from "../UI/Map/ShowOverlayRasterLayer"
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -82,6 +83,10 @@ export default class ThemeViewState implements SpecialVisualizationState {
|
|||
readonly geolocation: GeoLocationHandler
|
||||
|
||||
readonly lastClickObject: WritableFeatureSource
|
||||
readonly overlayLayerStates: ReadonlyMap<
|
||||
string,
|
||||
{ readonly isDisplayed: UIEventSource<boolean> }
|
||||
>
|
||||
|
||||
constructor(layout: LayoutConfig) {
|
||||
this.layout = layout
|
||||
|
@ -125,6 +130,21 @@ export default class ThemeViewState implements SpecialVisualizationState {
|
|||
const self = this
|
||||
this.layerState = new LayerState(this.osmConnection, layout.layers, layout.id)
|
||||
|
||||
{
|
||||
const overlayLayerStates = new Map<string, { isDisplayed: UIEventSource<boolean> }>()
|
||||
for (const rasterInfo of this.layout.tileLayerSources) {
|
||||
const isDisplayed = QueryParameters.GetBooleanQueryParameter(
|
||||
"overlay-" + rasterInfo.id,
|
||||
rasterInfo.defaultState ?? true,
|
||||
"Wether or not overlayer layer " + rasterInfo.id + " is shown"
|
||||
)
|
||||
const state = { isDisplayed }
|
||||
overlayLayerStates.set(rasterInfo.id, state)
|
||||
new ShowOverlayRasterLayer(rasterInfo, this.map, this.mapProperties, state)
|
||||
}
|
||||
this.overlayLayerStates = overlayLayerStates
|
||||
}
|
||||
|
||||
{
|
||||
/* Setup the layout source
|
||||
* A bit tricky, as this is heavily intertwined with the 'changes'-element, which generate a stream of new and changed features too
|
||||
|
|
|
@ -1,68 +0,0 @@
|
|||
import { VariableUiElement } from "../Base/VariableUIElement"
|
||||
import Toggle from "../Input/Toggle"
|
||||
import Combine from "../Base/Combine"
|
||||
import Translations from "../i18n/Translations"
|
||||
import { Translation } from "../i18n/Translation"
|
||||
import Svg from "../../Svg"
|
||||
import { ImmutableStore, Store, UIEventSource } from "../../Logic/UIEventSource"
|
||||
import FilteredLayer from "../../Models/FilteredLayer"
|
||||
import TilesourceConfig from "../../Models/ThemeConfig/TilesourceConfig"
|
||||
import Loc from "../../Models/Loc"
|
||||
|
||||
export default class FilterView extends VariableUiElement {
|
||||
constructor(
|
||||
filteredLayer: Store<FilteredLayer[]>,
|
||||
tileLayers: { config: TilesourceConfig; isDisplayed: UIEventSource<boolean> }[],
|
||||
state: {
|
||||
readonly availableBackgroundLayers?: Store<BaseLayer[]>
|
||||
readonly featureSwitchBackgroundSelection?: UIEventSource<boolean>
|
||||
readonly featureSwitchIsDebugging?: UIEventSource<boolean>
|
||||
readonly locationControl?: UIEventSource<Loc>
|
||||
readonly featureSwitchMoreQuests: Store<boolean>
|
||||
}
|
||||
) {
|
||||
super(
|
||||
filteredLayer.map((filteredLayers) => {
|
||||
// Create the views which toggle layers (and filters them) ...
|
||||
let elements = filteredLayers
|
||||
?.map((l) =>
|
||||
FilterView.createOneFilteredLayerElement(l, state)?.SetClass("filter-panel")
|
||||
)
|
||||
?.filter((l) => l !== undefined)
|
||||
elements[0].SetClass("first-filter-panel")
|
||||
|
||||
// ... create views for non-interactive layers ...
|
||||
elements = elements.concat(
|
||||
tileLayers.map((tl) => FilterView.createOverlayToggle(state, tl))
|
||||
)
|
||||
|
||||
return elements
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
private static createOverlayToggle(
|
||||
state: { locationControl?: UIEventSource<Loc> },
|
||||
config: { config: TilesourceConfig; isDisplayed: UIEventSource<boolean> }
|
||||
) {
|
||||
const iconStyle = "width:1.5rem;height:1.5rem;margin-left:1.25rem;flex-shrink: 0;"
|
||||
|
||||
const icon = new Combine([Svg.checkbox_filled]).SetStyle(iconStyle)
|
||||
const iconUnselected = new Combine([Svg.checkbox_empty]).SetStyle(iconStyle)
|
||||
const name: Translation = config.config.name
|
||||
|
||||
const styledNameChecked = name.Clone().SetStyle("font-size:large").SetClass("ml-2")
|
||||
const styledNameUnChecked = name.Clone().SetStyle("font-size:large").SetClass("ml-2")
|
||||
|
||||
const style = "display:flex;align-items:center;padding:0.5rem 0;"
|
||||
const layerChecked = new Combine([icon, styledNameChecked])
|
||||
.SetStyle(style)
|
||||
.onClick(() => config.isDisplayed.setData(false))
|
||||
|
||||
const layerNotChecked = new Combine([iconUnselected, styledNameUnChecked])
|
||||
.SetStyle(style)
|
||||
.onClick(() => config.isDisplayed.setData(true))
|
||||
|
||||
return new Toggle(layerChecked, layerNotChecked, config.isDisplayed)
|
||||
}
|
||||
}
|
47
UI/BigComponents/OverlayToggle.svelte
Normal file
47
UI/BigComponents/OverlayToggle.svelte
Normal file
|
@ -0,0 +1,47 @@
|
|||
<script lang="ts">/**
|
||||
* The OverlayToggle shows a single toggle to enable or disable an overlay
|
||||
*/
|
||||
import Checkbox from "../Base/Checkbox.svelte";
|
||||
import { onDestroy } from "svelte";
|
||||
import { UIEventSource } from "../../Logic/UIEventSource";
|
||||
import Tr from "../Base/Tr.svelte";
|
||||
import Translations from "../i18n/Translations";
|
||||
import type { RasterLayerProperties } from "../../Models/RasterLayers";
|
||||
import { Translation } from "../i18n/Translation";
|
||||
|
||||
export let layerproperties : RasterLayerProperties
|
||||
export let state: {isDisplayed: UIEventSource<boolean>};
|
||||
export let zoomlevel: UIEventSource<number>;
|
||||
export let highlightedLayer: UIEventSource<string> | undefined;
|
||||
|
||||
let isDisplayed: boolean = state.isDisplayed.data;
|
||||
onDestroy(state.isDisplayed.addCallbackAndRunD(d => {
|
||||
isDisplayed = d;
|
||||
return false;
|
||||
}));
|
||||
|
||||
|
||||
let mainElem: HTMLElement;
|
||||
$: onDestroy(
|
||||
highlightedLayer.addCallbackAndRun(highlightedLayer => {
|
||||
if (highlightedLayer === layerproperties.id) {
|
||||
mainElem?.classList?.add("glowing-shadow");
|
||||
} else {
|
||||
mainElem?.classList?.remove("glowing-shadow");
|
||||
}
|
||||
})
|
||||
);
|
||||
</script>
|
||||
{#if layerproperties.name}
|
||||
<div bind:this={mainElem}>
|
||||
<label class="flex gap-1">
|
||||
<Checkbox selected={state.isDisplayed} />
|
||||
<Tr t={new Translation(layerproperties.name)}/>
|
||||
{#if $zoomlevel < layerproperties.min_zoom}
|
||||
<span class="alert">
|
||||
<Tr t={Translations.t.general.layerSelection.zoomInToSeeThisLayer} />
|
||||
</span>
|
||||
{/if}
|
||||
</label>
|
||||
</div>
|
||||
{/if}
|
|
@ -1,6 +1,6 @@
|
|||
import { Store, UIEventSource } from "../../Logic/UIEventSource"
|
||||
import type { Map as MLMap } from "maplibre-gl"
|
||||
import { Map as MlMap } from "maplibre-gl"
|
||||
import { Map as MlMap, SourceSpecification } from "maplibre-gl"
|
||||
import { RasterLayerPolygon, RasterLayerProperties } from "../../Models/RasterLayers"
|
||||
import { Utils } from "../../Utils"
|
||||
import { BBox } from "../../Logic/BBox"
|
||||
|
@ -37,6 +37,7 @@ export class MapLibreAdaptor implements MapProperties, ExportableMap {
|
|||
readonly allowZooming: UIEventSource<true | boolean | undefined>
|
||||
readonly lastClickLocation: Store<undefined | { lon: number; lat: number }>
|
||||
readonly minzoom: UIEventSource<number>
|
||||
readonly maxzoom: UIEventSource<number>
|
||||
private readonly _maplibreMap: Store<MLMap>
|
||||
/**
|
||||
* Used for internal bookkeeping (to remove a rasterLayer when done loading)
|
||||
|
@ -50,12 +51,14 @@ export class MapLibreAdaptor implements MapProperties, ExportableMap {
|
|||
this.location = state?.location ?? new UIEventSource({ lon: 0, lat: 0 })
|
||||
this.zoom = state?.zoom ?? new UIEventSource(1)
|
||||
this.minzoom = state?.minzoom ?? new UIEventSource(0)
|
||||
this.maxzoom = state?.maxzoom ?? new UIEventSource(24)
|
||||
this.zoom.addCallbackAndRunD((z) => {
|
||||
if (z < this.minzoom.data) {
|
||||
this.zoom.setData(this.minzoom.data)
|
||||
}
|
||||
if (z > 24) {
|
||||
this.zoom.setData(24)
|
||||
const max = Math.min(24, this.maxzoom.data ?? 24)
|
||||
if (z > max) {
|
||||
this.zoom.setData(max)
|
||||
}
|
||||
})
|
||||
this.maxbounds = state?.maxbounds ?? new UIEventSource(undefined)
|
||||
|
@ -90,6 +93,7 @@ export class MapLibreAdaptor implements MapProperties, ExportableMap {
|
|||
self.setAllowMoving(self.allowMoving.data)
|
||||
self.setAllowZooming(self.allowZooming.data)
|
||||
self.setMinzoom(self.minzoom.data)
|
||||
self.setMaxzoom(self.maxzoom.data)
|
||||
self.setBounds(self.bounds.data)
|
||||
})
|
||||
self.MoveMapToCurrentLoc(self.location.data)
|
||||
|
@ -98,6 +102,7 @@ export class MapLibreAdaptor implements MapProperties, ExportableMap {
|
|||
self.setAllowMoving(self.allowMoving.data)
|
||||
self.setAllowZooming(self.allowZooming.data)
|
||||
self.setMinzoom(self.minzoom.data)
|
||||
self.setMaxzoom(self.maxzoom.data)
|
||||
self.setBounds(self.bounds.data)
|
||||
this.updateStores()
|
||||
map.on("moveend", () => this.updateStores())
|
||||
|
@ -146,10 +151,23 @@ export class MapLibreAdaptor implements MapProperties, ExportableMap {
|
|||
}
|
||||
}
|
||||
|
||||
public static prepareWmsSource(layer: RasterLayerProperties): SourceSpecification {
|
||||
return {
|
||||
type: "raster",
|
||||
// use the tiles option to specify a 256WMS tile source URL
|
||||
// https://maplibre.org/maplibre-gl-js-docs/style-spec/sources/
|
||||
tiles: [MapLibreAdaptor.prepareWmsURL(layer.url, layer["tile-size"] ?? 256)],
|
||||
tileSize: layer["tile-size"] ?? 256,
|
||||
minzoom: layer["min_zoom"] ?? 1,
|
||||
maxzoom: layer["max_zoom"] ?? 25,
|
||||
// scheme: background["type"] === "tms" ? "tms" : "xyz",
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares an ELI-URL to be compatible with mapbox
|
||||
*/
|
||||
private static prepareWmsURL(url: string, size: number = 256) {
|
||||
private static prepareWmsURL(url: string, size: number = 256): string {
|
||||
// ELI: LAYERS=OGWRGB13_15VL&STYLES=&FORMAT=image/jpeg&CRS={proj}&WIDTH={width}&HEIGHT={height}&BBOX={bbox}&VERSION=1.3.0&SERVICE=WMS&REQUEST=GetMap
|
||||
// PROD: SERVICE=WMS&REQUEST=GetMap&LAYERS=OGWRGB13_15VL&STYLES=&FORMAT=image/jpeg&TRANSPARENT=false&VERSION=1.3.0&WIDTH=256&HEIGHT=256&CRS=EPSG:3857&BBOX=488585.4847988467,6590094.830634755,489196.9810251281,6590706.32686104
|
||||
|
||||
|
@ -342,16 +360,7 @@ export class MapLibreAdaptor implements MapProperties, ExportableMap {
|
|||
return
|
||||
}
|
||||
|
||||
map.addSource(background.id, {
|
||||
type: "raster",
|
||||
// use the tiles option to specify a 256WMS tile source URL
|
||||
// https://maplibre.org/maplibre-gl-js-docs/style-spec/sources/
|
||||
tiles: [MapLibreAdaptor.prepareWmsURL(background.url, background["tile-size"] ?? 256)],
|
||||
tileSize: background["tile-size"] ?? 256,
|
||||
minzoom: background["min_zoom"] ?? 1,
|
||||
maxzoom: background["max_zoom"] ?? 25,
|
||||
// scheme: background["type"] === "tms" ? "tms" : "xyz",
|
||||
})
|
||||
map.addSource(background.id, MapLibreAdaptor.prepareWmsSource(background))
|
||||
|
||||
map.addLayer(
|
||||
{
|
||||
|
@ -405,6 +414,14 @@ export class MapLibreAdaptor implements MapProperties, ExportableMap {
|
|||
map.setMinZoom(minzoom)
|
||||
}
|
||||
|
||||
private setMaxzoom(maxzoom: number) {
|
||||
const map = this._maplibreMap.data
|
||||
if (map === undefined) {
|
||||
return
|
||||
}
|
||||
map.setMaxZoom(maxzoom)
|
||||
}
|
||||
|
||||
private setAllowZooming(allow: true | boolean | undefined) {
|
||||
const map = this._maplibreMap.data
|
||||
if (map === undefined) {
|
||||
|
|
92
UI/Map/ShowOverlayRasterLayer.ts
Normal file
92
UI/Map/ShowOverlayRasterLayer.ts
Normal file
|
@ -0,0 +1,92 @@
|
|||
import { RasterLayerProperties } from "../../Models/RasterLayers"
|
||||
import { Store, UIEventSource } from "../../Logic/UIEventSource"
|
||||
import { Map as MlMap } from "maplibre-gl"
|
||||
import { Utils } from "../../Utils"
|
||||
import { MapLibreAdaptor } from "./MapLibreAdaptor"
|
||||
|
||||
export default class ShowOverlayRasterLayer {
|
||||
private readonly _map: UIEventSource<MlMap>
|
||||
private readonly _layer: RasterLayerProperties
|
||||
private readonly _mapProperties?: { zoom: Store<number> }
|
||||
private _mllayer
|
||||
private readonly _isDisplayed?: Store<boolean>
|
||||
|
||||
constructor(
|
||||
layer: RasterLayerProperties,
|
||||
map: UIEventSource<MlMap>,
|
||||
mapProperties?: { zoom: Store<number> },
|
||||
options?: {
|
||||
isDisplayed?: Store<boolean>
|
||||
}
|
||||
) {
|
||||
this._mapProperties = mapProperties
|
||||
this._layer = layer
|
||||
this._map = map
|
||||
this._isDisplayed = options?.isDisplayed
|
||||
const self = this
|
||||
map.addCallbackAndRunD((map) => {
|
||||
self.addLayer()
|
||||
map.on("load", () => {
|
||||
self.addLayer()
|
||||
})
|
||||
})
|
||||
this.addLayer()
|
||||
|
||||
options?.isDisplayed?.addCallbackAndRun(() => {
|
||||
self.setVisibility()
|
||||
})
|
||||
|
||||
mapProperties?.zoom?.addCallbackAndRun(() => {
|
||||
self.setVisibility()
|
||||
})
|
||||
}
|
||||
|
||||
private setVisibility() {
|
||||
let zoom = this._mapProperties?.zoom?.data
|
||||
let withinRange = zoom === undefined || zoom > this._layer.min_zoom
|
||||
let isDisplayed = (this._isDisplayed?.data ?? true) && withinRange
|
||||
this._map.data?.setLayoutProperty(
|
||||
this._layer.id,
|
||||
"visibility",
|
||||
isDisplayed ? "visible" : "none"
|
||||
)
|
||||
}
|
||||
|
||||
private async awaitStyleIsLoaded(): Promise<void> {
|
||||
const map = this._map.data
|
||||
if (map === undefined) {
|
||||
return
|
||||
}
|
||||
while (!map?.isStyleLoaded()) {
|
||||
await Utils.waitFor(250)
|
||||
}
|
||||
}
|
||||
|
||||
private async addLayer() {
|
||||
const map = this._map.data
|
||||
console.log("Attempting to add ", this._layer.id)
|
||||
if (map === undefined) {
|
||||
return
|
||||
}
|
||||
await this.awaitStyleIsLoaded()
|
||||
if (this._mllayer) {
|
||||
// Already initialized
|
||||
return
|
||||
}
|
||||
const background: RasterLayerProperties = this._layer
|
||||
|
||||
map.addSource(background.id, MapLibreAdaptor.prepareWmsSource(background))
|
||||
this._mllayer = map.addLayer({
|
||||
id: background.id,
|
||||
type: "raster",
|
||||
source: background.id,
|
||||
paint: {},
|
||||
})
|
||||
map.setLayoutProperty(
|
||||
this._layer.id,
|
||||
"visibility",
|
||||
this._isDisplayed?.data ?? true ? "visible" : "none"
|
||||
)
|
||||
this.setVisibility()
|
||||
}
|
||||
}
|
|
@ -75,6 +75,7 @@ export class MinimapViz implements SpecialVisualization {
|
|||
const mlmap = new UIEventSource(undefined)
|
||||
const mla = new MapLibreAdaptor(mlmap)
|
||||
|
||||
mla.maxzoom.setData(17)
|
||||
let zoom = 18
|
||||
if (args[0]) {
|
||||
const parsed = Number(args[0])
|
||||
|
|
|
@ -1,43 +0,0 @@
|
|||
import * as L from "leaflet"
|
||||
import TilesourceConfig from "../../Models/ThemeConfig/TilesourceConfig"
|
||||
import { UIEventSource } from "../../Logic/UIEventSource"
|
||||
import ShowOverlayLayer from "./ShowOverlayLayer"
|
||||
|
||||
// TODO port this to maplibre!
|
||||
export default class ShowOverlayLayerImplementation {
|
||||
public static Implement() {
|
||||
ShowOverlayLayer.implementation = ShowOverlayLayerImplementation.AddToMap
|
||||
}
|
||||
|
||||
public static AddToMap(
|
||||
config: TilesourceConfig,
|
||||
leafletMap: UIEventSource<any>,
|
||||
isShown: UIEventSource<boolean> = undefined
|
||||
) {
|
||||
leafletMap.map((leaflet) => {
|
||||
if (leaflet === undefined) {
|
||||
return
|
||||
}
|
||||
|
||||
const tileLayer = L.tileLayer(config.source, {
|
||||
attribution: "",
|
||||
maxZoom: config.maxzoom,
|
||||
minZoom: config.minzoom,
|
||||
// @ts-ignore
|
||||
wmts: false,
|
||||
})
|
||||
|
||||
if (isShown === undefined) {
|
||||
tileLayer.addTo(leaflet)
|
||||
}
|
||||
|
||||
isShown?.addCallbackAndRunD((isShown) => {
|
||||
if (isShown) {
|
||||
tileLayer.addTo(leaflet)
|
||||
} else {
|
||||
leaflet.removeLayer(tileLayer)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
|
@ -34,7 +34,7 @@
|
|||
import Hotkeys from "./Base/Hotkeys";
|
||||
import { VariableUiElement } from "./Base/VariableUIElement";
|
||||
import SvelteUIElement from "./Base/SvelteUIElement";
|
||||
import { onDestroy } from "svelte";
|
||||
import OverlayToggle from "./BigComponents/OverlayToggle.svelte";
|
||||
|
||||
export let state: ThemeViewState;
|
||||
let layout = state.layout;
|
||||
|
@ -53,7 +53,7 @@
|
|||
}
|
||||
|
||||
const tags = state.featureProperties.getStore(selectedElement.properties.id);
|
||||
return new SvelteUIElement(SelectedElementView, {state, layer, selectedElement, tags})
|
||||
return new SvelteUIElement(SelectedElementView, { state, layer, selectedElement, tags });
|
||||
}, [selectedLayer]);
|
||||
|
||||
|
||||
|
@ -160,6 +160,14 @@
|
|||
<Filterview zoomlevel={state.mapProperties.zoom} filteredLayer={state.layerState.filteredLayers.get(layer.id)}
|
||||
highlightedLayer={state.guistate.highlightedLayerInFilters}></Filterview>
|
||||
{/each}
|
||||
{#each layout.tileLayerSources as tilesource}
|
||||
<OverlayToggle
|
||||
layerproperties={tilesource}
|
||||
state={state.overlayLayerStates.get(tilesource.id)}
|
||||
highlightedLayer={state.guistate.highlightedLayerInFilters}
|
||||
zoomlevel={state.mapProperties.zoom}
|
||||
/>
|
||||
{/each}
|
||||
<If condition={state.featureSwitches.featureSwitchBackgroundSelection}>
|
||||
<RasterLayerPicker {availableLayers} value={mapproperties.rasterLayer}></RasterLayerPicker>
|
||||
</If>
|
||||
|
|
|
@ -30,10 +30,10 @@
|
|||
"tileLayerSources": [
|
||||
{
|
||||
"id": "property-boundaries",
|
||||
"source": "https://tiles.osmuk.org/PropertyBoundaries/{z}/{x}/{y}.png",
|
||||
"url": "https://tiles.osmuk.org/PropertyBoundaries/{z}/{x}/{y}.png",
|
||||
"isOverlay": true,
|
||||
"minZoom": 18,
|
||||
"maxZoom": 20,
|
||||
"min_zoom": 18,
|
||||
"max_zoom": 20,
|
||||
"defaultState": false,
|
||||
"name": {
|
||||
"en": "Property boundaries by osmuk.org",
|
||||
|
|
Loading…
Reference in a new issue