forked from MapComplete/MapComplete
		
	
		
			
				
	
	
		
			99 lines
		
	
	
	
		
			3.9 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			99 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
 | |
|     }
 | |
| }
 |