// LIBRARIES import { Map } from "@maptiler/sdk"; import { polygon } from "@turf/helpers"; import area from "@turf/area"; // PROJECT import { SelectedFeature } from "../types/types"; import { MAP_STYLE } from "@/constants"; import { LAYERS } from "../layers"; import { layerFilterEq, layerFilterIn } from "@/utilities/layers"; import { UIService } from "./ui-service"; /** * Service for managing map interactions and state */ export class MapService { private uiService: UIService; private selected: Array = []; public map: Map; /** * Creates a new MapService instance * @param uiService - The UI service for updating interface elements */ public constructor(uiService: UIService) { this.uiService = uiService; this.map = new Map({ container: "map", style: MAP_STYLE, }); } /** * Loads the map and initializes all event listeners */ public load() { this.map.on("load", () => { // Aggiunge tutti i layer custom a codice per le interazioni this.map.addLayer(LAYERS.BUILDING_HIGHLIGHT); this.map.addLayer(LAYERS.BUILDING_SELECT); // Handle map hover. this.map.on("mousemove", (e) => { // Prende le features solo di questi livelli const features = this.map.queryRenderedFeatures(e.point, { layers: ["building_matteo", "road_network"], }); // Aggiorna latitudine e longitudine nel container al mouse over. this.uiService.$lnglat.html(`${e.lngLat.lng}
${e.lngLat.lat}`); if (features && features.length > 0) { // Prendo l'ID della top level feature in hover const hovered = features[0]; const hoveredId = hovered.id; if (hoveredId) { // Aggiorna l'ID della feature nel container delle informazioni. this.uiService.$info.html(hoveredId?.toString() || "None"); this.map.setFilter( LAYERS.BUILDING_HIGHLIGHT.id, layerFilterEq(hoveredId), ); this.map.getCanvas().style.cursor = "pointer"; } } else { this.uiService.$info.html("None"); this.map.getCanvas().style.cursor = "default"; this.map.setFilter(LAYERS.BUILDING_HIGHLIGHT.id, layerFilterEq()); } }); this.handleClicks(); // PROVA ROUTE // route( // "routed-foot", // "12.234413623809816,45.486327517344776", // "12.228652238845827,45.48756107353653", // ).then((res) => { // map.addSource("route", { // type: "geojson", // data: { // type: "Feature", // properties: {}, // geometry: res.routes[0].geometry as GeoJSON.Geometry, // }, // }); // map.addLayer({ // id: "prova", // type: "line", // source: "route", // layout: { // "line-join": "round", // "line-cap": "round", // }, // paint: { // "line-color": "#FF0000", // Colore blu // "line-width": 5, // Spessore in pixel // "line-opacity": 0.8, // }, // }); // }); }); } /** * Handles click events on map features */ public handleClicks() { this.map.on("click", (e) => { const features = this.map.queryRenderedFeatures(e.point, { layers: ["building_matteo"], }); if (features && features.length > 0) { const clicked = features[0]; const clickedId: number = typeof clicked.id == "string" ? parseInt(clicked.id) : clicked.id || 0; let clickedArea: number = 0.0; // Calculate the area of the selected. if ( clicked.geometry.type == "Polygon" && clicked.geometry.coordinates.length > 0 ) { let clickedCoords = clicked.geometry.coordinates[0]; let clickedPolygon = polygon([clickedCoords]); clickedArea = Math.trunc(area(clickedPolygon)); } // Handle "selected list" with deletion. const i = this.selected.findIndex((u) => u.id == clickedId); if (i !== -1) { this.selected.splice(i, 1); } else { this.selected.push({ id: clickedId, area: clickedArea, }); } // Update the "selected" list. this.uiService.updateSelectedList(this.selected); if (this.selected.length === 0) { this.uiService.$selected.append("
None
"); } // Sets the selected layer. if (clickedId) { this.map.setFilter(LAYERS.BUILDING_HIGHLIGHT.id, layerFilterEq()); this.map.setFilter( LAYERS.BUILDING_SELECT.id, layerFilterIn( this.selected.map((s) => { return s.id; }), ), ); this.map.getCanvas().style.cursor = "pointer"; } } else { this.map.getCanvas().style.cursor = "default"; } }); } }