Feature(clustering): fix count update on filters, fix hiding when zoomed out to much

This commit is contained in:
Pieter Vander Vennet 2025-07-24 19:28:34 +02:00
parent 0048c091d0
commit 63e9d20255
5 changed files with 26 additions and 21 deletions

View file

@ -1,12 +1,13 @@
import { Store, UIEventSource } from "../../UIEventSource" import { Store, UIEventSource } from "../../UIEventSource"
import FilteredLayer from "../../../Models/FilteredLayer" import FilteredLayer from "../../../Models/FilteredLayer"
import { FeatureSource } from "../FeatureSource" import { FeatureSource } from "../FeatureSource"
import { Feature } from "geojson" import { Feature, Geometry } from "geojson"
import { GlobalFilter } from "../../../Models/GlobalFilter" import { GlobalFilter } from "../../../Models/GlobalFilter"
import { OsmTags } from "../../../Models/OsmFeature"
export default class FilteringFeatureSource implements FeatureSource { export default class FilteringFeatureSource<T extends Feature = Feature<Geometry, OsmTags>> implements FeatureSource<T> {
public features: UIEventSource<Feature[]> = new UIEventSource([]) public readonly features: UIEventSource<T[]> = new UIEventSource([])
private readonly upstream: FeatureSource private readonly upstream: FeatureSource<T>
private readonly _fetchStore?: (id: string) => Store<Record<string, string>> private readonly _fetchStore?: (id: string) => Store<Record<string, string>>
private readonly _globalFilters?: Store<GlobalFilter[]> private readonly _globalFilters?: Store<GlobalFilter[]>
private readonly _alreadyRegistered = new Set<Store<any>>() private readonly _alreadyRegistered = new Set<Store<any>>()
@ -18,7 +19,7 @@ export default class FilteringFeatureSource implements FeatureSource {
constructor( constructor(
layer: FilteredLayer, layer: FilteredLayer,
upstream: FeatureSource, upstream: FeatureSource<T>,
fetchStore?: (id: string) => Store<Record<string, string>>, fetchStore?: (id: string) => Store<Record<string, string>>,
globalFilters?: Store<GlobalFilter[]>, globalFilters?: Store<GlobalFilter[]>,
metataggingUpdated?: Store<any>, metataggingUpdated?: Store<any>,
@ -40,7 +41,7 @@ export default class FilteringFeatureSource implements FeatureSource {
}) })
layer.appliedFilters.forEach((value) => layer.appliedFilters.forEach((value) =>
value.addCallback((_) => { value.addCallback(() => {
this.update() this.update()
}) })
) )
@ -68,7 +69,7 @@ export default class FilteringFeatureSource implements FeatureSource {
private update() { private update() {
const layer = this._layer const layer = this._layer
const features: Feature[] = this.upstream.features.data ?? [] const features: T[] = this.upstream.features.data ?? []
const includedFeatureIds = new Set<string>() const includedFeatureIds = new Set<string>()
const globalFilters = this._globalFilters?.data?.map((f) => f) const globalFilters = this._globalFilters?.data?.map((f) => f)
const zoomlevel = this._zoomlevel?.data const zoomlevel = this._zoomlevel?.data
@ -121,10 +122,9 @@ export default class FilteringFeatureSource implements FeatureSource {
} }
this._alreadyRegistered.add(src) this._alreadyRegistered.add(src)
const self = this
// Add a callback as a changed tag might change the filter // Add a callback as a changed tag might change the filter
src.addCallbackAndRunD((_) => { src.addCallbackAndRunD(() => {
self._is_dirty.setData(true) this._is_dirty.setData(true)
}) })
} }
} }

View file

@ -12,8 +12,8 @@ export class IfVisibleFeatureSource<T extends Feature> implements FeatureSource<
let dirty = false let dirty = false
upstream.features.addCallbackAndRun(features => { upstream.features.addCallbackAndRun(features => {
if (!visible.data) { if (!visible.data) {
console.log(">>> not writing data as not visible")
dirty = true dirty = true
this._features.set([])
return return
} }
this._features.set(features) this._features.set(features)

View file

@ -140,13 +140,14 @@ export class ClusterGrouping implements FeatureSource<Feature<Point, { total_met
} }
} }
const features: Feature<Point, { total_metric: string, id: string }>[] = [] const features: Feature<Point, { total_metric: string, id: string }>[] = []
const now = new Date().getTime() + ""
for (const tileId of countPerTile.keys()) { for (const tileId of countPerTile.keys()) {
const coordinates = Tiles.centerPointOf(tileId) const coordinates = Tiles.centerPointOf(tileId)
features.push({ features.push({
type: "Feature", type: "Feature",
properties: { properties: {
total_metric: "" + countPerTile.get(tileId), total_metric: "" + countPerTile.get(tileId),
id: "clustered_all_" + tileId id: "clustered_all_" + tileId + "_" + now // We add the date to force a fresh ID every time, this makes sure values are updated
}, },
geometry: { geometry: {
type: "Point", type: "Point",

View file

@ -79,12 +79,12 @@ export class PointRenderingLayer {
} }
allowed_location_codes.forEach((code) => { allowed_location_codes.forEach((code) => {
const marker = this._allMarkers.get(<OsmId>selected.properties.id) const marker = this._allMarkers.get(<OsmId>selected.properties.id)
.get(code) ?.get(code)
?.getElement() ?.getElement()
if (marker === undefined) { if (marker === undefined) {
return return
} }
marker?.classList?.add("selected") marker.classList?.add("selected")
this._markedAsSelected.push(marker) this._markedAsSelected.push(marker)
}) })
}) })

View file

@ -388,20 +388,26 @@ export default class ShowDataLayer {
}) })
} }
/**
* Show the data, unless they are clustered.
* This method does _not_ add the clusters themselves to the map,
* this should be done independently. In a themeViewGui, this is done by the 'addSpecialLayers'
* @see ClusterGrouping
* @param mlmap
* @param state
* @param options
*/
public static showLayerClustered(mlmap: Store<MlMap>, public static showLayerClustered(mlmap: Store<MlMap>,
state: { mapProperties: { zoom: UIEventSource<number> } }, state: { mapProperties: { zoom: UIEventSource<number> } },
options: ShowDataLayerOptions & { layer: LayerConfig } options: ShowDataLayerOptions & { layer: LayerConfig }
) { ) {
options.preprocessPoints = feats => { options.preprocessPoints = feats =>
const clustering = new ClusteringFeatureSource(feats, state.mapProperties.zoom.map(z => z + 2), new ClusteringFeatureSource(feats, state.mapProperties.zoom.map(z => z + 2),
options.layer.id, options.layer.id,
{ {
cutoff: 7, cutoff: 7,
showSummaryAt: "tilecenter" showSummaryAt: "tilecenter"
}) })
return clustering
}
new ShowDataLayer(mlmap, options) new ShowDataLayer(mlmap, options)
} }
@ -417,8 +423,6 @@ export default class ShowDataLayer {
}) })
} }
public destruct() {}
private static zoomToCurrentFeatures(map: MlMap, features: Feature[]) { private static zoomToCurrentFeatures(map: MlMap, features: Feature[]) {
if (!features || !map || features.length == 0) { if (!features || !map || features.length == 0) {
return return