From 6a90f16fe11847e035249f9d6cf287f1296e06a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A2u=20Cao?= Date: Thu, 15 Jan 2026 22:00:23 +0700 Subject: [PATCH] Add OSM service, map click handler --- app/components/map.gjs | 66 ++++++++++++++++++++++++++++-------------- app/services/osm.js | 25 ++++++++++++++++ 2 files changed, 69 insertions(+), 22 deletions(-) create mode 100644 app/services/osm.js diff --git a/app/components/map.gjs b/app/components/map.gjs index 1a245e0..cd033c3 100644 --- a/app/components/map.gjs +++ b/app/components/map.gjs @@ -1,36 +1,58 @@ +import Component from '@glimmer/component'; +import { service } from '@ember/service'; import { modifier } from 'ember-modifier'; import 'ol/ol.css'; import Map from 'ol/Map.js'; import { defaults as defaultControls } from 'ol/control.js'; import View from 'ol/View.js'; -import { fromLonLat } from 'ol/proj.js'; +import { fromLonLat, toLonLat } from 'ol/proj.js'; import LayerGroup from 'ol/layer/Group.js'; import { apply } from 'ol-mapbox-style'; -let mapInstance; +export default class MapComponent extends Component { + @service osm; -const setupMap = modifier((element) => { - if (mapInstance) return; + mapInstance; - const openfreemap = new LayerGroup(); + setupMap = modifier((element) => { + if (this.mapInstance) return; - mapInstance = new Map({ - target: element, - layers: [openfreemap], - controls: defaultControls({ zoom: false }), - view: new View({ - center: fromLonLat([99.05738, 7.56087]), - zoom: 12.5, - projection: 'EPSG:3857', - }), + const openfreemap = new LayerGroup(); + + this.mapInstance = new Map({ + target: element, + layers: [openfreemap], + controls: defaultControls({ zoom: false }), + view: new View({ + center: fromLonLat([99.05738, 7.56087]), + zoom: 12.5, + projection: 'EPSG:3857', + }), + }); + + apply(openfreemap, 'https://tiles.openfreemap.org/styles/positron'); + + this.mapInstance.on('singleclick', this.handleMapClick); }); - apply(openfreemap, 'https://tiles.openfreemap.org/styles/positron'); -}); + handleMapClick = async (event) => { + const coords = toLonLat(event.coordinate); + const [lon, lat] = coords; - + console.log(`Clicked at: ${lat}, ${lon}`); + + try { + const pois = await this.osm.getNearbyPois(lat, lon); + console.log('Nearby POIs:', pois); + } catch (error) { + console.error('Failed to fetch POIs:', error); + } + }; + + +} diff --git a/app/services/osm.js b/app/services/osm.js new file mode 100644 index 0000000..20e1898 --- /dev/null +++ b/app/services/osm.js @@ -0,0 +1,25 @@ +import Service from '@ember/service'; + +export default class OsmService extends Service { + async getNearbyPois(lat, lon, radius = 200) { + const query = ` +[out:json][timeout:25]; +( + nwr["amenity"](around:${radius},${lat},${lon}); + nwr["shop"](around:${radius},${lat},${lon}); + nwr["tourism"](around:${radius},${lat},${lon}); + nwr["leisure"](around:${radius},${lat},${lon}); + nwr["historic"](around:${radius},${lat},${lon}); +); +out center; + `.trim(); + + const url = `https://overpass-api.de/api/interpreter?data=${encodeURIComponent( + query + )}`; + const res = await fetch(url); + if (!res.ok) throw new Error('Overpass request failed'); + const data = await res.json(); + return data.elements; + } +}