forked from MapComplete/MapComplete
		
	
		
			
				
	
	
		
			104 lines
		
	
	
	
		
			3.7 KiB
		
	
	
	
		
			Svelte
		
	
	
	
	
	
			
		
		
	
	
			104 lines
		
	
	
	
		
			3.7 KiB
		
	
	
	
		
			Svelte
		
	
	
	
	
	
| <script lang="ts">
 | |
|   /**
 | |
|    * This component shows a map which focuses on a single OSM-Way (linestring) feature.
 | |
|    * Clicking the map will add a new 'scissor' point, projected on the linestring (and possible snapped to an already existing node within the linestring;
 | |
|    * clicking this point again will remove it.
 | |
|    * The bound 'value' will contain the location of these projected points.
 | |
|    * Points are not coalesced with already existing nodes within the way; it is up to the code actually splitting the way to decide to reuse an existing point or not
 | |
|    *
 | |
|    * This component is _not_ responsible for the rest of the flow, e.g. the confirm button
 | |
|    */
 | |
|   import LayerConfig from "../../Models/ThemeConfig/LayerConfig";
 | |
|   import type { LayerConfigJson } from "../../Models/ThemeConfig/Json/LayerConfigJson";
 | |
|   import split_point from "../../assets/layers/split_point/split_point.json";
 | |
|   import split_road from "../../assets/layers/split_road/split_road.json";
 | |
|   import { UIEventSource } from "../../Logic/UIEventSource";
 | |
|   import { Map as MlMap } from "maplibre-gl";
 | |
|   import type { MapProperties } from "../../Models/MapProperties";
 | |
|   import { MapLibreAdaptor } from "../Map/MapLibreAdaptor";
 | |
|   import MaplibreMap from "../Map/MaplibreMap.svelte";
 | |
|   import { OsmWay } from "../../Logic/Osm/OsmObject";
 | |
|   import ShowDataLayer from "../Map/ShowDataLayer";
 | |
|   import StaticFeatureSource from "../../Logic/FeatureSource/Sources/StaticFeatureSource";
 | |
|   import { GeoOperations } from "../../Logic/GeoOperations";
 | |
|   import { BBox } from "../../Logic/BBox";
 | |
|   import type { Feature, LineString, Point } from "geojson";
 | |
| 
 | |
|   const splitpoint_style = new LayerConfig(
 | |
|     <LayerConfigJson>split_point,
 | |
|     "(BUILTIN) SplitRoadWizard.ts",
 | |
|     true
 | |
|   ) as const;
 | |
| 
 | |
|   const splitroad_style = new LayerConfig(
 | |
|     <LayerConfigJson>split_road,
 | |
|     "(BUILTIN) SplitRoadWizard.ts",
 | |
|     true
 | |
|   ) as const;
 | |
| 
 | |
|   /**
 | |
|    * The way to focus on
 | |
|    */
 | |
|   export let osmWay: OsmWay
 | |
|   /**
 | |
|    * How to render this layer.
 | |
|    * A default is given
 | |
|    */
 | |
|   export let layer: LayerConfig = splitroad_style
 | |
|     /**
 | |
|      * Optional: use these properties to set e.g. background layer
 | |
|      */
 | |
|   export let mapProperties: undefined | Partial<MapProperties> = undefined;
 | |
|   
 | |
|   let map: UIEventSource<MlMap> = new UIEventSource<MlMap>(undefined);
 | |
|   let adaptor = new MapLibreAdaptor(map, mapProperties);
 | |
|   
 | |
|   const wayGeojson: Feature<LineString> = GeoOperations.forceLineString( osmWay.asGeoJson())
 | |
|   adaptor.location.setData(GeoOperations.centerpointCoordinatesObj(wayGeojson))
 | |
|   adaptor.bounds.setData(BBox.get(wayGeojson).pad(2))
 | |
|   adaptor.maxbounds.setData(BBox.get(wayGeojson).pad(2))
 | |
|   
 | |
|   new ShowDataLayer(map, {
 | |
|     features: new StaticFeatureSource([wayGeojson]),
 | |
|     drawMarkers: false,
 | |
|     layer: layer
 | |
|   })
 | |
|   
 | |
|   export let splitPoints: UIEventSource< Feature<
 | |
|     Point,
 | |
|     {
 | |
|       id: number
 | |
|       index: number
 | |
|       dist: number
 | |
|       location: number
 | |
|     }
 | |
|   >[]> = new UIEventSource([])
 | |
|   const splitPointsFS = new StaticFeatureSource(splitPoints)
 | |
|   
 | |
|   new ShowDataLayer(map, {
 | |
|     layer: splitpoint_style,
 | |
|     features: splitPointsFS,
 | |
|     onClick: (clickedFeature: Feature) => {
 | |
|       console.log("Clicked feature is", clickedFeature, splitPoints.data)
 | |
|       const i = splitPoints.data.findIndex(f => f === clickedFeature)
 | |
|       if(i < 0){
 | |
|         return
 | |
|       }
 | |
|       splitPoints.data.splice(i, 1)
 | |
|       splitPoints.ping()
 | |
|     }
 | |
|   })
 | |
|   let id = 0
 | |
|   adaptor.lastClickLocation.addCallbackD(({lon, lat}) => {
 | |
|     const projected = GeoOperations.nearestPoint(wayGeojson, [lon, lat])
 | |
|     
 | |
|     projected.properties["id"] = id
 | |
|     id++
 | |
|     splitPoints.data.push(<any> projected)
 | |
|     splitPoints.ping()
 | |
|   })
 | |
|   
 | |
| </script>
 | |
| <div class="w-full h-full">
 | |
|   <MaplibreMap {map}></MaplibreMap>
 | |
| </div>
 |