import * as L from 'leaflet'; import { Feature, FeatureCollection, GeoJSON } from 'geojson'; interface PlaceModel { name: string; address: string; open_hours: string; icon: string; description: string; latitude: number; longitude: number; } async function loadPlaces(): Promise> { return await fetch('places/').then(response => response.json()); } function toLeafletPlaces(backendPlaces: Array): GeoJSON { let result: FeatureCollection = { type: "FeatureCollection", features: new Array(), } for (const place of backendPlaces) { result.features.push({ "type": "Feature", "properties": { "name": place.name, "address": place.address, "open_hours": place.open_hours, "icon": place.icon, "description": place.description }, "geometry": { "type": "Point", "coordinates": [place.latitude, place.longitude] } }); } return result; } async function setupMap(): Promise { const backendPlaces = await loadPlaces(); const leafletPlaces = toLeafletPlaces(backendPlaces); /* Set up the map*/ const map = new L.Map('map'); /* Create the tile layer with correct attribution*/ const osmUrl = 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png'; const osmAttrib = 'Mapa © OpenStreetMap'; const osm = new L.TileLayer(osmUrl, { minZoom: 4, maxZoom: 20, attribution: osmAttrib }); /* Start the map in Santiago */ map.setView(new L.LatLng(-33.45, -70.666667), 13); /* Try to get user position, if not, put the map in Santiago again */ map.locate({ setView: true, maxZoom: 16 }) .on('locationerror', function(_event: L.LocationEvent) { map.setView(new L.LatLng(-33.45, -70.666667), 13); }); map.addLayer(osm); function onEachFeature(feature: Feature, layer: L.Layer) { if (feature.properties) { let popupStr = "

" + feature.properties.name + "

"; popupStr += "
    " if (feature.properties.address) popupStr += "
  • Dirección: " + feature.properties.address + "
  • "; if (feature.properties.open_hours) popupStr += "
  • Horario: " + feature.properties.open_hours + "
  • "; if (feature.properties.description) popupStr += "
  • " + feature.properties.description + "
  • "; popupStr += "
"; layer.bindPopup(popupStr); } } /* Icons */ const icons = new Map(); icons.set('bar', new L.Icon({ iconUrl: 'icons/bar.svg' })); icons.set('coffee', new L.Icon({ iconUrl: 'icons/coffee.svg' })); icons.set('dining', new L.Icon({ iconUrl: 'icons/dining.svg' })); icons.set('food', new L.Icon({ iconUrl: 'icons/food.svg' })); icons.set('jazz', new L.Icon({ iconUrl: 'icons/saxophone.svg' })); icons.set('library', new L.Icon({ iconUrl: 'icons/book.svg' })); icons.set('marker', new L.Icon({ iconUrl: 'icons/marker.svg' })); icons.set('mask', new L.Icon({ iconUrl: 'icons/mask.svg' })); icons.set('museum', new L.Icon({ iconUrl: 'icons/museum.svg' })); icons.set('shop', new L.Icon({ iconUrl: 'icons/store.svg' })); for (let [_name, icon] of icons) { icon.options.iconSize = [36, 36]; icon.options.popupAnchor = [0, -18]; } function pointToLayer(feature: Feature, latlng: L.LatLng) { let markerIcon = null; if (feature.properties && feature.properties.icon) { markerIcon = icons.get(feature.properties.icon); } if (markerIcon !== null && markerIcon !== undefined) return L.marker(latlng, { icon: markerIcon }); else return L.marker(latlng); } map.addLayer(L.geoJSON(leafletPlaces, { onEachFeature: onEachFeature, pointToLayer: pointToLayer })); }