diff --git a/Customizations/JSON/LayoutConfig.ts b/Customizations/JSON/LayoutConfig.ts index e849206..dfb3d54 100644 --- a/Customizations/JSON/LayoutConfig.ts +++ b/Customizations/JSON/LayoutConfig.ts @@ -24,7 +24,9 @@ export default class LayoutConfig { public readonly roamingRenderings: TagRenderingConfig[]; public readonly defaultBackgroundId?: string; public readonly layers: LayerConfig[]; - public readonly clustering: { }; + public readonly clustering?: { + maxZoom: number + }; public readonly hideFromOverview: boolean; public readonly enableUserBadge: boolean; @@ -76,22 +78,28 @@ export default class LayoutConfig { ); this.defaultBackgroundId = json.defaultBackgroundId; this.layers = json.layers.map((layer, i) => { - if (typeof layer === "string") + if (typeof layer === "string"){ if (SharedLayers.sharedLayers[layer] !== undefined) { return SharedLayers.sharedLayers[layer]; } else { throw "Unkown fixed layer " + layer; } + } return new LayerConfig(layer, this.roamingRenderings, `${this.id}.layers[${i}]`); }); - this.clustering = json.clustering ?? false; + this.clustering = undefined; + if(json.clustering){ + this.clustering = { + maxZoom : json.clustering.maxZoom ?? 18 + } + } if(this.clustering){ for (const layer of this.layers) { if(layer.wayHandling !== LayerConfig.WAYHANDLING_CENTER_ONLY){ - throw "In order to allow clustering, every layer must be set to CENTER_ONLY"; + console.error("WARNING: In order to allow clustering, every layer must be set to CENTER_ONLY. Layer", layer.id,"does not respect this for layout",this.id); } } } diff --git a/Customizations/JSON/LayoutConfigJson.ts b/Customizations/JSON/LayoutConfigJson.ts index 2e2a89f..03c3729 100644 --- a/Customizations/JSON/LayoutConfigJson.ts +++ b/Customizations/JSON/LayoutConfigJson.ts @@ -126,7 +126,10 @@ export interface LayoutConfigJson { /** * If defined, data will be clustered. */ - clustering: { + clustering: { + /** + * All zoom levels above 'maxzoom' are not clustered anymore + */ maxZoom?: number }, diff --git a/InitUiElements.ts b/InitUiElements.ts index 0be4f41..d3fbee5 100644 --- a/InitUiElements.ts +++ b/InitUiElements.ts @@ -421,7 +421,9 @@ export class InitUiElements { MetaTagging.addMetatags(features); }) - new ShowDataLayer(source.features, State.state.leafletMap, flayers); + new ShowDataLayer(source.features, State.state.leafletMap, + State.state.locationControl.map(l => l.zoom), + State.state.layoutToUse.data); } diff --git a/UI/ShowDataLayer.ts b/UI/ShowDataLayer.ts index 6ad8e2d..04dc80a 100644 --- a/UI/ShowDataLayer.ts +++ b/UI/ShowDataLayer.ts @@ -20,6 +20,7 @@ export default class ShowDataLayer { constructor(features: UIEventSource<{ feature: any, freshness: Date }[]>, leafletMap: UIEventSource, + zoom: UIEventSource, layoutToUse: LayoutConfig) { this._leafletMap = leafletMap; const self = this; @@ -41,11 +42,14 @@ export default class ShowDataLayer { const feats = features.data.map(ff => ff.feature); let geoLayer = self.CreateGeojsonLayer(feats) - const cl = window["L"]; - const cluster = cl.markerClusterGroup(); - cluster.addLayer(geoLayer); - geoLayer = cluster; - + if (layoutToUse.clustering !== undefined) { + if (layoutToUse.clustering.maxZoom >= zoom.data) { + const cl = window["L"]; + const cluster = cl.markerClusterGroup(); + cluster.addLayer(geoLayer); + geoLayer = cluster; + } + } if (oldGeoLayer) { mp.removeLayer(oldGeoLayer); @@ -56,6 +60,9 @@ export default class ShowDataLayer { features.addCallbackAndRun(() => update()); leafletMap.addCallback(() => update()); + zoom.map(z => (layoutToUse.clustering?.maxZoom ?? 0) >= z).addCallback(() => { + update(); + }); } diff --git a/Utils.ts b/Utils.ts index 25a0158..7866df2 100644 --- a/Utils.ts +++ b/Utils.ts @@ -178,5 +178,5 @@ export class Utils { } } - + } diff --git a/assets/layers/trees/tree_nodes.json b/assets/layers/trees/tree_nodes.json index fc0fc59..3493c1c 100644 --- a/assets/layers/trees/tree_nodes.json +++ b/assets/layers/trees/tree_nodes.json @@ -4,7 +4,7 @@ "nl": "Boom", "en": "Tree" }, - "minzoom": 18, + "minzoom": 14, "overpassTags": { "and": ["natural=tree"] }, @@ -347,22 +347,23 @@ ], "hideUnderlayingFeaturesMinPercentage": 0, "icon": { - "render": "./assets/themes/trees/unknown.svg", + "render": "circle:#ffffff;./assets/themes/trees/unknown.svg", "mappings": [ { "if": { "and": ["leaf_type=broadleaved"] }, - "then": "./assets/themes/trees/broadleaved.svg" + "then": "circle:#ffffff;./assets/themes/trees/broadleaved.svg" }, { "if": { "and": ["leaf_type=needleleaved"] }, - "then": "./assets/themes/trees/needleleaved.svg" + "then": "circle:#ffffff;./assets/themes/trees/needleleaved.svg" } ] }, + "wayHandling": 1, "width": { "render": "8" }, diff --git a/assets/themes/trees/trees.json b/assets/themes/trees/trees.json index 4133fcf..26ad343 100644 --- a/assets/themes/trees/trees.json +++ b/assets/themes/trees/trees.json @@ -24,6 +24,9 @@ "startZoom": 8, "widenFactor": 0.01, "socialImage": "./assets/themes/trees/logo.svg", + "clustering": { + "maxZoom": 18 + }, "layers": [ "tree_nodes" ],