Add OSM service, map click handler
Some checks failed
CI / Lint (push) Has been cancelled
CI / Test (push) Has been cancelled

This commit is contained in:
Râu Cao 2026-01-15 22:00:23 +07:00
parent caa48537bc
commit 6a90f16fe1
Signed by: raucao
GPG Key ID: 37036C356E56CC51
2 changed files with 69 additions and 22 deletions

View File

@ -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;
<template>
<div
{{setupMap}}
style="position: absolute; inset: 0;"
></div>
</template>
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);
}
};
<template>
<div
{{this.setupMap}}
style="position: absolute; inset: 0;"
></div>
</template>
}

25
app/services/osm.js Normal file
View File

@ -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;
}
}