code re-organization
This commit is contained in:
172
src/services/map-service.ts
Normal file
172
src/services/map-service.ts
Normal file
@@ -0,0 +1,172 @@
|
||||
// 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<SelectedFeature> = [];
|
||||
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}<br>${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;
|
||||
|
||||
// Aggiorna l'ID della feature nel container delle informazioni.
|
||||
this.uiService.$info.html(hoveredId?.toString() || "");
|
||||
|
||||
if (hoveredId) {
|
||||
this.map.setFilter(
|
||||
LAYERS.BUILDING_HIGHLIGHT.id,
|
||||
layerFilterEq(hoveredId),
|
||||
);
|
||||
this.map.getCanvas().style.cursor = "pointer";
|
||||
}
|
||||
} else {
|
||||
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("<div>None</div>");
|
||||
}
|
||||
|
||||
// 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";
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user