forked from MapComplete/MapComplete
		
	
		
			
	
	
		
			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
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 |