https://github.com/Leaflet/Leaflet
https://github.com/smeijer/leaflet-geosearch
| <!DOCTYPE html> | |
| <html> | |
| <head> | |
| <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" /> | |
| <title>Display a map</title> | |
| <link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" /> | |
| <script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script> | |
| <link rel="stylesheet" | |
| href="https://cdn.jsdelivr.net/npm/leaflet.locatecontrol@v0.81.1/dist/L.Control.Locate.min.css" /> | |
| <script src="https://cdn.jsdelivr.net/npm/leaflet.locatecontrol@v0.81.1/dist/L.Control.Locate.min.js" | |
| charset="utf-8"></script> | |
| <script src="https://unpkg.com/leaflet-providers@latest/leaflet-providers.js"></script> | |
| <link rel="stylesheet" href="https://unpkg.com/leaflet-geosearch@latest/dist/geosearch.css" /> | |
| <script src="https://unpkg.com/leaflet-geosearch@latest/dist/bundle.min.js"></script> | |
| <link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.1.0/css/font-awesome.min.css" rel="stylesheet"> | |
| <script src="https://cdn.jsdelivr.net/npm/leaflet-sidebar@0.2.4/src/L.Control.Sidebar.min.js"></script> | |
| <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/leaflet-sidebar@0.2.4/src/L.Control.Sidebar.min.css"> | |
| <style> | |
| #map { | |
| position: absolute; | |
| top: 0; | |
| right: 0; | |
| bottom: 0; | |
| left: 0; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div id="sidebar"> | |
| <h1>Details</h1> | |
| </div> | |
| <div id="map" class="sidebar-map"> | |
| </div> | |
| <p> | |
| <a href="https://www.openstreetmap.org/copyright" target="_blank" rel="noopener">© OpenStreetMap | |
| contributors</a> | |
| </p> | |
| <script> | |
| /** set default coord & zoom **/ | |
| const map = L.map('map', { | |
| // minZoom: 0, | |
| // maxZoom: 25 | |
| }).setView([-0.8674005, 131.3051903], 12.9); | |
| /** set map tile endpoint **/ | |
| L.tileLayer(`https://tile.openstreetmap.org/{z}/{x}/{y}.{ext}`, { | |
| // tileSize: 512, | |
| // zoomOffset: -1, | |
| // minZoom: 1, | |
| ext: 'png', | |
| // minZoom: 0, | |
| // maxZoom: 20, | |
| attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors', | |
| crossOrigin: true | |
| }).addTo(map); | |
| /** set style **/ | |
| L.tileLayer.provider('OpenStreetMap.Mapnik').addTo(map); | |
| /** add sidebar **/ | |
| var sidebar = L.control.sidebar('sidebar', { | |
| position: 'right' | |
| }); | |
| map.addControl(sidebar); | |
| /** set current location **/ | |
| const lc = L.control.locate({ | |
| locateOptions: { enableHighAccuracy: true } | |
| }).addTo(map); | |
| /** set searchbox location **/ | |
| const search = new GeoSearch.GeoSearchControl({ | |
| provider: new GeoSearch.OpenStreetMapProvider(), | |
| style: 'bar', | |
| maxMarkers: 1, // optional: number - default 1 | |
| retainZoomLevel: false, // optional: true|false - default false | |
| animateZoom: true, // optional: true|false - default true | |
| autoClose: false, // optional: true|false - default false | |
| searchLabel: 'Pencarian', // optional: string - default 'Enter address' | |
| keepResult: false, // optional: true|false - default false | |
| updateMap: true, // optional: true|false - default true | |
| showMarker: true, // optional: true|false - default true | |
| showPopup: false, // optional: true|false - default false | |
| popupFormat: ({ query, result }) => result.label, // optional: function - default returns result label, | |
| resultFormat: ({ result }) => result.label, // optional: function - default returns result label | |
| marker: { | |
| // optional: L.Marker - default L.Icon.Default | |
| icon: new L.Icon.Default(), | |
| draggable: false, | |
| } | |
| }); | |
| map.addControl(search); | |
| var marker; | |
| const hideKey = [ | |
| 'place_id', | |
| 'osm_type', | |
| 'osm_id', | |
| 'place_rank', | |
| 'importance', | |
| 'licence', | |
| 'boundingbox']; | |
| /** | |
| * @param {Object} coord | |
| * @param {number} coord.lat | |
| * @param {number} coord.lg | |
| **/ | |
| const getMapDetails = async ({ lat = -0.8674005, lng = 131.3051903 }) => { | |
| if (marker) | |
| map.removeLayer(marker); | |
| marker = L.marker({ lat: lat, lng: lng }).addTo(map); | |
| try { | |
| var details = | |
| await (await fetch(`https://nominatim.openstreetmap.org/reverse?lat=${lat}&lon=${lng}&format=json`)) | |
| .json() | |
| // show json content | |
| var content = `<h1>Details</h1>` + Object.entries(details).map(([key, value]) => { | |
| if (hideKey.includes(key)) | |
| return ''; | |
| else if (key === 'address') | |
| return Object.entries(value).map(([k, v]) => | |
| `<div style="padding-bottom: 8px"><div style="font-weight: bold;"> ${k} </div><span>${v}</span></div>`).join(''); | |
| else return `<div style="padding-bottom: 8px"><div style="font-weight: bold;"> ${key} </div><span>${value}</span></div>`; | |
| }).join(''); | |
| sidebar.setContent(content); | |
| sidebar.show(); | |
| // TODO: | |
| // save details json data | |
| } catch (error) { | |
| alert('Terjadi kesalahan'); | |
| } | |
| } | |
| /** event handle **/ | |
| map.on('geosearch/showlocation', async (e) => | |
| getMapDetails({ lat: e.location.y, lng: e.location.x })); | |
| map.on('click', (e) => | |
| setTimeout(async () => | |
| await getMapDetails({ lat: e.latlng.lat, lng: e.latlng.lng }), 1000)); | |
| /** start get current location **/ | |
| // lc.start(); | |
| </script> | |
| </body> | |
| </html> |