diff --git a/src/constants.ts b/src/constants.ts index 7565406..71b0515 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -1 +1,9 @@ +/** + * Initial zoom level for the map + */ export const INITIAL_ZOOM = 17; + +/** + * MapTiler style URL for the map + */ +export const MAP_STYLE = import.meta.env.VITE_MAPTILER_STYLE; diff --git a/src/game.ts b/src/game.ts new file mode 100644 index 0000000..b802f35 --- /dev/null +++ b/src/game.ts @@ -0,0 +1,9 @@ +/** + * Game class for managing game state and logic + */ +class Game { + /** + * Starts the game + */ + public start = () => {}; +} diff --git a/src/layers.ts b/src/layers.ts index b29fe84..6e1758a 100644 --- a/src/layers.ts +++ b/src/layers.ts @@ -1,6 +1,10 @@ -import { FillLayerSpecification, LineLayerSpecification } from "@maptiler/sdk"; +import { FillLayerSpecification } from "@maptiler/sdk"; +/** + * Configuration for all custom map layers + */ export const LAYERS = { + /** Layer for highlighting hovered buildings */ BUILDING_HIGHLIGHT: { id: "building-highlight", type: "fill", @@ -13,6 +17,7 @@ export const LAYERS = { filter: ["==", ["id"], ""], } as FillLayerSpecification, + /** Layer for highlighting selected buildings */ BUILDING_SELECT: { id: "building-select", type: "fill", @@ -24,17 +29,4 @@ export const LAYERS = { }, filter: ["==", ["id"], ""], } as FillLayerSpecification, - - ROAD_HIGHLIGHT: { - id: "road-highlight", - type: "line", - paint: { - "line-color": "#FF0000", - "line-width": 4, - "line-opacity": 1, - }, - source: "maptiler_planet_v4", - "source-layer": "road", - filter: ["==", ["id"], ""], - } as LineLayerSpecification, }; diff --git a/src/main.ts b/src/main.ts index bd3b9c6..007537e 100644 --- a/src/main.ts +++ b/src/main.ts @@ -6,18 +6,16 @@ import "@maptiler/sdk/dist/maptiler-sdk.css"; // LIBRARIES import $ from "jquery"; -import { FilterSpecification, Map, config } from "@maptiler/sdk"; +import { config } from "@maptiler/sdk"; import { createIcons, Locate, LocateFixed } from "lucide"; -import area from "@turf/area"; -import { polygon } from "@turf/helpers"; // PROJECT -import { LAYERS } from "@/layers"; -import { panToCurrentLocation, route } from "@/utilities/geo"; +import { panToCurrentLocation } from "@/utilities/geo"; +import { MapService } from "@/services/map-service"; +import { UIService } from "./services/ui-service"; // ENV const API_KEY = import.meta.env.VITE_MAPTILER_API_KEY || ""; -const MAP_STYLE = import.meta.env.VITE_MAPTILER_STYLE; createIcons({ icons: { @@ -26,187 +24,14 @@ createIcons({ }, }); -// TODO -// WEBSOCKET TBD!! -// const ws = new WebSocket(`ws://${import.meta.env.VITE_SERVER_URL}/ws`); -// ws.onopen = () => { -// console.log("opened"); -// }; -// ws.onmessage = (ev) => { -// console.log("il server dice"); -// console.log(ev.data); -// }; - config.apiKey = API_KEY; -interface SelectedFeature { - id: number; - area: number; -} - -const $info = $("#layer"); -const $lnglat = $("#lnglat"); -const $selected = $("#selected"); - -let selected: Array = []; - -const map = new Map({ - container: "map", - style: MAP_STYLE, -}); +const mapService = new MapService(new UIService()); +mapService.load(); $("#locate").on("click", (e) => { e.preventDefault(); - panToCurrentLocation(map); + panToCurrentLocation(mapService.map); }); -// Funzione helper per settare i filtri dei layer. -// Per non avere array hardcoded.] -const layerFilterEq = (id?: string | number) => { - return ["==", ["id"], id ? id : ""] as FilterSpecification; -}; -const layerFilterIn = (ids: Array) => { - return ["in", ["id"], ["literal", ids]] as FilterSpecification; -}; - -map.on("load", () => { - // Aggiunge tutti i layer custom a codice per le interazioni - map.addLayer(LAYERS.BUILDING_HIGHLIGHT); - map.addLayer(LAYERS.BUILDING_SELECT); - map.addLayer(LAYERS.ROAD_HIGHLIGHT); - - // Handle map hover. - map.on("mousemove", (e) => { - // Prende le features solo di questi livelli - const features = map.queryRenderedFeatures(e.point, { - layers: ["building_matteo", "road_network"], - }); - - // Aggiorna latitudine e longitudine nel container al mouse over. - $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; - - // Aggiorna l'ID della feature nel container delle informazioni. - $info.html(hoveredId?.toString() || ""); - - if (hoveredId) { - map.setFilter(LAYERS.BUILDING_HIGHLIGHT.id, layerFilterEq(hoveredId)); - // map.setFilter(LAYERS.ROAD_HIGHLIGHT.id, layerFilterEq(hoveredId)); - map.getCanvas().style.cursor = "pointer"; - } - } else { - map.getCanvas().style.cursor = "default"; - map.setFilter(LAYERS.BUILDING_HIGHLIGHT.id, layerFilterEq()); - // map.setFilter(LAYERS.ROAD_HIGHLIGHT.id, layerFilterEq()); - } - }); - - // Handle map click. - map.on("click", (e) => { - const features = 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; - - // TODO - // WEBSOCKET TBD! - // ws.send( - // JSON.stringify({ - // clicked: clickedId, - // }), - // ); - - // 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 = selected.findIndex((u) => u.id == clickedId); - if (i !== -1) { - selected.splice(i, 1); - } else { - selected.push({ - id: clickedId, - area: clickedArea, - }); - } - - // Update the "selected" list. - const selectedList = $("