3 import * as L from 'leaflet';
4 import 'leaflet-minimap';
5 import 'leaflet/dist/leaflet.css';
6 import 'leaflet-minimap/dist/Control.MiniMap.min.css';
8 import { mapState } from '../state/MapState.svelte.js';
9 import MapPosition from '../components/MapPosition.svelte';
12 display_minimap = false,
13 current_result = null,
14 position_marker = null
20 function mapViewboxAsString(map) {
21 var bounds = map.getBounds();
22 var west = bounds.getWest();
23 var east = bounds.getEast();
25 if ((east - west) >= 360) { // covers more than whole planet
26 west = map.getCenter().lng - 179.999;
27 east = map.getCenter().lng + 179.999;
29 east = L.latLng(77, east).wrap().lng;
30 west = L.latLng(77, west).wrap().lng;
33 west.toFixed(5), // left
34 bounds.getNorth().toFixed(5), // top
35 east.toFixed(5), // right
36 bounds.getSouth().toFixed(5) // bottom
40 function setMapState() {
41 mapState.viewboxStr = mapViewboxAsString(map);
42 mapState.center = map.getCenter();
43 mapState.zoom = map.getZoom();
46 function createMap(container) {
47 const attribution = Nominatim_Config.Map_Tile_Attribution;
49 map = new L.map(container, {
50 attributionControl: false,
51 scrollWheelZoom: true, // !L.Browser.touch,
53 center: L.latLng(Nominatim_Config.Map_Default_Lat,
54 Nominatim_Config.Map_Default_Lon),
55 zoom: Nominatim_Config.Map_Default_Zoom
57 if (typeof Nominatim_Config.Map_Default_Bounds !== 'undefined'
58 && Nominatim_Config.Map_Default_Bounds) {
59 map.fitBounds(Nominatim_Config.Map_Default_Bounds);
62 if (attribution && attribution.length) {
63 L.control.attribution({ prefix: '<a href="https://leafletjs.com/">Leaflet</a>' }).addTo(map);
68 L.control.scale().addTo(map);
70 L.tileLayer(Nominatim_Config.Map_Tile_URL, {
71 attribution: attribution
74 if (display_minimap) {
75 let osm2 = new L.TileLayer(Nominatim_Config.Map_Tile_URL, {
78 attribution: attribution
80 new L.Control.MiniMap(osm2, { toggleDisplay: true }).addTo(map);
83 map.on('move', setMapState);
84 map.on('mousemove', (e) => { mapState.mousePos = e.latlng; });
85 map.on('click', (e) => { mapState.lastClick = e.latlng; });
88 function mapAction(container) {
90 setMapData(position_marker, current_result);
100 function parse_and_normalize_geojson_string(part) {
101 // normalize places the geometry into a featurecollection, similar to
102 // https://github.com/mapbox/geojson-normalize
103 var parsed_geojson = {
104 type: 'FeatureCollection',
113 return parsed_geojson;
116 function resetMapData() {
117 if (!map) { return; }
119 dataLayers.forEach(function (layer) {
120 map.removeLayer(layer);
124 function setMapData(marker, aFeature) {
125 if (!map) { return; }
130 // We don't need a marker, but L.circle would change radius when you zoom in/out
131 let cm = L.circleMarker(
136 fillColor: '#ff7800',
143 cm.bindTooltip(`Search (${marker[0]},${marker[1]})`).openTooltip();
148 var search_params = new URLSearchParams(window.location.search);
149 var viewbox = search_params.get('viewbox');
151 let coords = viewbox.split(','); // <x1>,<y1>,<x2>,<y2>
152 let bounds = L.latLngBounds([coords[1], coords[0]], [coords[3], coords[2]]);
153 let viewbox_on_map = L.rectangle(bounds, {
161 map.addLayer(viewbox_on_map);
162 dataLayers.push(viewbox_on_map);
165 if (!aFeature) return;
167 let lat = aFeature.centroid ? aFeature.centroid.coordinates[1] : aFeature.lat;
168 let lon = aFeature.centroid ? aFeature.centroid.coordinates[0] : aFeature.lon;
169 let geojson = aFeature.geometry || aFeature.geojson;
172 let circle = L.circleMarker([lat, lon], {
173 radius: 10, weight: 2, fillColor: '#ff7800', color: 'blue', opacity: 0.75
175 if (marker) { // reverse result
176 circle.bindTooltip('Result').openTooltip();
178 map.addLayer(circle);
179 dataLayers.push(circle);
184 var geojson_layer = L.geoJson(
185 // https://leafletjs.com/reference-1.7.1.html#path-option
186 parse_and_normalize_geojson_string(geojson),
189 return { interactive: false, color: 'blue' };
193 map.addLayer(geojson_layer);
194 dataLayers.push(geojson_layer);
195 map.fitBounds(geojson_layer.getBounds());
196 } else if (lat && lon && marker) {
197 map.fitBounds([[lat, lon], marker], { padding: [50, 50] });
198 } else if (lat && lon) {
199 map.setView([lat, lon], 10);
204 setMapData(position_marker, current_result);
209 <div id="map" use:mapAction></div>
218 @media (max-width: 768px) {