100 lines
3.9 KiB
TypeScript
100 lines
3.9 KiB
TypeScript
|
import {Store, UIEventSource} from "../../Logic/UIEventSource";
|
||
|
import Loc from "../../Models/Loc";
|
||
|
import Minimap from "../Base/Minimap";
|
||
|
import ShowDataMultiLayer from "../ShowDataLayer/ShowDataMultiLayer";
|
||
|
import StaticFeatureSource from "../../Logic/FeatureSource/Sources/StaticFeatureSource";
|
||
|
import {SpecialVisualization} from "../SpecialVisualization";
|
||
|
|
||
|
export class MinimapViz implements SpecialVisualization {
|
||
|
funcName = "minimap"
|
||
|
docs = "A small map showing the selected feature."
|
||
|
args = [
|
||
|
{
|
||
|
doc: "The (maximum) zoomlevel: the target zoomlevel after fitting the entire feature. The minimap will fit the entire feature, then zoom out to this zoom level. The higher, the more zoomed in with 1 being the entire world and 19 being really close",
|
||
|
name: "zoomlevel",
|
||
|
defaultValue: "18",
|
||
|
},
|
||
|
{
|
||
|
doc: "(Matches all resting arguments) This argument should be the key of a property of the feature. The corresponding value is interpreted as either the id or the a list of ID's. The features with these ID's will be shown on this minimap. (Note: if the key is 'id', list interpration is disabled)",
|
||
|
name: "idKey",
|
||
|
defaultValue: "id",
|
||
|
},
|
||
|
]
|
||
|
example:
|
||
|
"`{minimap()}`, `{minimap(17, id, _list_of_embedded_feature_ids_calculated_by_calculated_tag):height:10rem; border: 2px solid black}`"
|
||
|
|
||
|
constr(state, tagSource, args, _) {
|
||
|
if (state === undefined) {
|
||
|
return undefined
|
||
|
}
|
||
|
const keys = [...args]
|
||
|
keys.splice(0, 1)
|
||
|
const featureStore = state.allElements.ContainingFeatures
|
||
|
const featuresToShow: Store<{ freshness: Date; feature: any }[]> =
|
||
|
tagSource.map((properties) => {
|
||
|
const features: { freshness: Date; feature: any }[] = []
|
||
|
for (const key of keys) {
|
||
|
const value = properties[key]
|
||
|
if (value === undefined || value === null) {
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
let idList = [value]
|
||
|
if (key !== "id" && value.startsWith("[")) {
|
||
|
// This is a list of values
|
||
|
idList = JSON.parse(value)
|
||
|
}
|
||
|
|
||
|
for (const id of idList) {
|
||
|
const feature = featureStore.get(id)
|
||
|
if (feature === undefined) {
|
||
|
console.warn("No feature found for id ", id)
|
||
|
continue
|
||
|
}
|
||
|
features.push({
|
||
|
freshness: new Date(),
|
||
|
feature,
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
return features
|
||
|
})
|
||
|
const properties = tagSource.data
|
||
|
let zoom = 18
|
||
|
if (args[0]) {
|
||
|
const parsed = Number(args[0])
|
||
|
if (!isNaN(parsed) && parsed > 0 && parsed < 25) {
|
||
|
zoom = parsed
|
||
|
}
|
||
|
}
|
||
|
const locationSource = new UIEventSource<Loc>({
|
||
|
lat: Number(properties._lat),
|
||
|
lon: Number(properties._lon),
|
||
|
zoom: zoom,
|
||
|
})
|
||
|
const minimap = Minimap.createMiniMap({
|
||
|
background: state.backgroundLayer,
|
||
|
location: locationSource,
|
||
|
allowMoving: false,
|
||
|
})
|
||
|
|
||
|
locationSource.addCallback((loc) => {
|
||
|
if (loc.zoom > zoom) {
|
||
|
// We zoom back
|
||
|
locationSource.data.zoom = zoom
|
||
|
locationSource.ping()
|
||
|
}
|
||
|
})
|
||
|
|
||
|
new ShowDataMultiLayer({
|
||
|
leafletMap: minimap["leafletMap"],
|
||
|
zoomToFeatures: true,
|
||
|
layers: state.filteredLayers,
|
||
|
features: new StaticFeatureSource(featuresToShow),
|
||
|
})
|
||
|
|
||
|
minimap.SetStyle("overflow: hidden; pointer-events: none;")
|
||
|
return minimap
|
||
|
}
|
||
|
}
|