refactoring: split all the states

This commit is contained in:
Pieter Vander Vennet 2023-03-25 02:48:24 +01:00
parent 4d48b1cf2b
commit 8e2f04c0d0
32 changed files with 411 additions and 395 deletions

View file

@ -14,12 +14,12 @@ import Constants from "../../Models/Constants"
*/
export class MapLibreAdaptor implements MapProperties {
private static maplibre_control_handlers = [
"scrollZoom",
"boxZoom",
// "scrollZoom",
// "boxZoom",
// "doubleClickZoom",
"dragRotate",
"dragPan",
"keyboard",
"doubleClickZoom",
"touchZoomRotate",
]
readonly location: UIEventSource<{ lon: number; lat: number }>

View file

@ -8,12 +8,13 @@ import PointRenderingConfig from "../../Models/ThemeConfig/PointRenderingConfig"
import { OsmTags } from "../../Models/OsmFeature"
import FeatureSource from "../../Logic/FeatureSource/FeatureSource"
import { BBox } from "../../Logic/BBox"
import { Feature, LineString } from "geojson"
import { Feature } from "geojson"
import ScrollableFullScreen from "../Base/ScrollableFullScreen"
import LineRenderingConfig from "../../Models/ThemeConfig/LineRenderingConfig"
import { Utils } from "../../Utils"
import * as range_layer from "../../assets/layers/range/range.json"
import { LayerConfigJson } from "../../Models/ThemeConfig/Json/LayerConfigJson"
class PointRenderingLayer {
private readonly _config: PointRenderingConfig
private readonly _fetchStore?: (id: string) => Store<OsmTags>
@ -44,6 +45,16 @@ class PointRenderingLayer {
const unseenKeys = new Set(cache.keys())
for (const location of this._config.location) {
for (const feature of features) {
if (feature?.geometry === undefined) {
console.warn(
"Got an invalid feature:",
features,
" while rendering",
location,
"of",
this._config
)
}
const loc = GeoOperations.featureToCoordinateWithRenderingType(
<any>feature,
location
@ -102,7 +113,14 @@ class PointRenderingLayer {
})
}
return new Marker(el).setLngLat(loc).setOffset(iconAnchor).addTo(this._map)
const marker = new Marker(el).setLngLat(loc).setOffset(iconAnchor).addTo(this._map)
store
.map((tags) => this._config.pitchAlignment.GetRenderValue(tags).Subs(tags).txt)
.addCallbackAndRun((pitchAligment) => marker.setPitchAlignment(pitchAligment))
store
.map((tags) => this._config.rotationAlignment.GetRenderValue(tags).Subs(tags).txt)
.addCallbackAndRun((pitchAligment) => marker.setRotationAlignment(pitchAligment))
return marker
}
}
@ -118,13 +136,17 @@ class LineRenderingLayer {
"offset",
"fill",
"fillColor",
]
] as const
private static readonly lineConfigKeysColor = ["color", "fillColor"] as const
private static readonly lineConfigKeysNumber = ["width", "offset"] as const
private readonly _map: MlMap
private readonly _config: LineRenderingConfig
private readonly _visibility?: Store<boolean>
private readonly _fetchStore?: (id: string) => Store<OsmTags>
private readonly _onClick?: (id: string) => void
private readonly _layername: string
private readonly _listenerInstalledOn: Set<string> = new Set<string>()
constructor(
map: MlMap,
@ -145,6 +167,39 @@ class LineRenderingLayer {
features.features.addCallbackAndRunD((features) => self.update(features))
}
private calculatePropsFor(
properties: Record<string, string>
): Partial<Record<typeof LineRenderingLayer.lineConfigKeys[number], string>> {
const calculatedProps = {}
const config = this._config
for (const key of LineRenderingLayer.lineConfigKeys) {
const v = config[key]?.GetRenderValue(properties)?.Subs(properties).txt
calculatedProps[key] = v
}
for (const key of LineRenderingLayer.lineConfigKeysColor) {
let v = config[key]?.GetRenderValue(properties)?.Subs(properties).txt
if (v === undefined) {
continue
}
console.log("Color", v)
if (v.length == 9 && v.startsWith("#")) {
// This includes opacity
calculatedProps[key + "-opacity"] = parseInt(v.substring(7), 16) / 256
v = v.substring(0, 7)
console.log("Color >", v, calculatedProps[key + "-opacity"])
}
calculatedProps[key] = v
}
for (const key of LineRenderingLayer.lineConfigKeysNumber) {
const v = config[key]?.GetRenderValue(properties)?.Subs(properties).txt
calculatedProps[key] = Number(v)
}
console.log("Calculated props:", calculatedProps, "for", properties.id)
return calculatedProps
}
private async update(features: Feature[]) {
const map = this._map
while (!map.isStyleLoaded()) {
@ -158,31 +213,14 @@ class LineRenderingLayer {
},
promoteId: "id",
})
for (let i = 0; i < features.length; i++) {
const feature = features[i]
const id = feature.properties.id ?? "" + i
const tags = this._fetchStore(id)
tags.addCallbackAndRunD((properties) => {
const config = this._config
const calculatedProps = {}
for (const key of LineRenderingLayer.lineConfigKeys) {
const v = config[key]?.GetRenderValue(properties)?.Subs(properties).txt
calculatedProps[key] = v
}
map.setFeatureState({ source: this._layername, id }, calculatedProps)
})
}
map.addLayer({
source: this._layername,
id: this._layername + "_line",
type: "line",
filter: ["in", ["geometry-type"], ["literal", ["LineString", "MultiLineString"]]],
layout: {},
paint: {
"line-color": ["feature-state", "color"],
"line-opacity": ["feature-state", "color-opacity"],
"line-width": ["feature-state", "width"],
"line-offset": ["feature-state", "offset"],
},
@ -205,12 +243,49 @@ class LineRenderingLayer {
layout: {},
paint: {
"fill-color": ["feature-state", "fillColor"],
"fill-opacity": 0.1,
},
})
for (let i = 0; i < features.length; i++) {
const feature = features[i]
const id = feature.properties.id ?? feature.id
console.log("ID is", id)
if (id === undefined) {
console.trace(
"Got a feature without ID; this causes rendering bugs:",
feature,
"from"
)
continue
}
if (this._listenerInstalledOn.has(id)) {
continue
}
if (this._fetchStore === undefined) {
map.setFeatureState(
{ source: this._layername, id },
this.calculatePropsFor(feature.properties)
)
} else {
const tags = this._fetchStore(id)
this._listenerInstalledOn.add(id)
tags.addCallbackAndRunD((properties) => {
map.setFeatureState(
{ source: this._layername, id },
this.calculatePropsFor(properties)
)
})
}
}
}
}
export default class ShowDataLayer {
private static rangeLayer = new LayerConfig(
<LayerConfigJson>range_layer,
"ShowDataLayer.ts:range.json"
)
private readonly _map: Store<MlMap>
private readonly _options: ShowDataLayerOptions & { layer: LayerConfig }
private readonly _popupCache: Map<string, ScrollableFullScreen>
@ -223,11 +298,6 @@ export default class ShowDataLayer {
map.addCallbackAndRunD((map) => self.initDrawFeatures(map))
}
private static rangeLayer = new LayerConfig(
<LayerConfigJson>range_layer,
"ShowDataLayer.ts:range.json"
)
public static showRange(
map: Store<MlMap>,
features: FeatureSource,
@ -241,6 +311,9 @@ export default class ShowDataLayer {
}
private openOrReusePopup(id: string): void {
if (!this._popupCache || !this._options.fetchStore) {
return
}
if (this._popupCache.has(id)) {
this._popupCache.get(id).Activate()
return
@ -267,11 +340,12 @@ export default class ShowDataLayer {
private initDrawFeatures(map: MlMap) {
const { features, doShowLayer, fetchStore, buildPopup } = this._options
const onClick = buildPopup === undefined ? undefined : (id) => this.openOrReusePopup(id)
for (const lineRenderingConfig of this._options.layer.lineRendering) {
for (let i = 0; i < this._options.layer.lineRendering.length; i++) {
const lineRenderingConfig = this._options.layer.lineRendering[i]
new LineRenderingLayer(
map,
features,
"test",
this._options.layer.id + "_linerendering_" + i,
lineRenderingConfig,
doShowLayer,
fetchStore,