forked from MapComplete/MapComplete
		
	
		
			
	
	
		
			105 lines
		
	
	
	
		
			3.7 KiB
		
	
	
	
		
			Svelte
		
	
	
	
	
	
		
		
			
		
	
	
			105 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> |