249 lines
8.8 KiB
Vue
249 lines
8.8 KiB
Vue
<script setup lang="ts">
|
|
import { onMounted, ref } from 'vue'
|
|
import { loadModules } from 'esri-loader'
|
|
import axios from 'axios'
|
|
|
|
import type { LocationObject } from '@/interface/index/Main'
|
|
|
|
const emit = defineEmits(['update:location'])
|
|
|
|
function updateLocation(latitude: number, longitude: number, namePOI: string) {
|
|
// ส่ง event ไปยัง parent component เพื่ออัพเดทค่า props
|
|
emit('update:location', latitude, longitude, namePOI)
|
|
}
|
|
|
|
const poiPlaceName = ref<string>('') // ชื่อพื้นที่ใกล้เคียง
|
|
|
|
// Replace ArcGIS api key
|
|
const apiKey = ref<string>(
|
|
'YLATgWuywoeRLHn6KImj5rg7UaP8bJoR9jiTldoCVBHlqFIebwMSA5wIXEmcYhwXwMHkmNISEYtUz3x0oiGIIx0bIXXnUwi0OzupoOEtDrQIsRPVtor7gaPpXEmH8TrNaMT3snf6zO_yujHLGzborg-L9aeAjTJn4ndL6f8qFmRzYcX93E2vyA-7XCufLYTRsdTE5Aq-9hnx1q9PmYVMqhAZpL7dWqn3JgO33fRXetk.'
|
|
// 'AAPK4f700a4324d04e9f8a1a134e0771ac45FXWawdCl-OotFfr52gz9XKxTDJTpDzw_YYcwbmKDDyAJswf14FoPyw0qBkN64DvP'
|
|
)
|
|
const zoomMap = ref<number>(18)
|
|
|
|
async function initializeMap() {
|
|
try {
|
|
// Load modules of ArcGIS
|
|
loadModules([
|
|
'esri/config',
|
|
'esri/Map',
|
|
'esri/views/MapView',
|
|
'esri/geometry/Point',
|
|
'esri/Graphic',
|
|
'esri/layers/TileLayer',
|
|
]).then(async ([esriConfig, Map, MapView, Point, Graphic, TileLayer]) => {
|
|
// Set apiKey
|
|
// esriConfig.apiKey =
|
|
// 'AAPK4f700a4324d04e9f8a1a134e0771ac45FXWawdCl-OotFfr52gz9XKxTDJTpDzw_YYcwbmKDDyAJswf14FoPyw0qBkN64DvP'
|
|
|
|
// Create a FeatureLayer using a custom server URL
|
|
// const hillshadeLayer = new TileLayer({
|
|
// url: `https://bmagis.bangkok.go.th/arcgis/rest/services/cache/BMA_3D_2D_Cache/MapServer`,
|
|
// })
|
|
|
|
const map = new Map({
|
|
basemap: 'streets',
|
|
// basemap: 'arcgis-topographic',
|
|
// layers: [hillshadeLayer],
|
|
})
|
|
|
|
navigator.geolocation.getCurrentPosition(async (position) => {
|
|
const { latitude, longitude } = position.coords
|
|
|
|
const mapView = new MapView({
|
|
container: 'mapViewDisplay',
|
|
map: map,
|
|
center: {
|
|
latitude: latitude,
|
|
longitude: longitude,
|
|
}, // Set the initial map center current position
|
|
|
|
zoom: zoomMap.value,
|
|
constraints: {
|
|
snapToZoom: false, // Disables snapping to the zoom level
|
|
minZoom: zoomMap.value, // Set minimum zoom level
|
|
maxZoom: zoomMap.value, // Set maximum zoom level (same as minZoom for fixed zoom)
|
|
},
|
|
|
|
ui: {
|
|
components: [], // Empty array to remove all default UI components
|
|
},
|
|
})
|
|
|
|
// ตำแหน่งของผู้ใช้
|
|
const userPoint = new Point({ longitude, latitude })
|
|
const userSymbol = {
|
|
type: 'picture-marker',
|
|
url: 'http://maps.google.com/mapfiles/ms/icons/red.png',
|
|
width: '32px',
|
|
height: '32px',
|
|
}
|
|
const userGraphic = new Graphic({
|
|
geometry: userPoint,
|
|
symbol: userSymbol,
|
|
})
|
|
mapView.graphics.add(userGraphic)
|
|
// Get POI place ยิงไปขอที่ server ของกทม.ก่อน
|
|
await axios
|
|
.get(
|
|
'https://bmagis.bangkok.go.th/portal/sharing/servers/e4732c3a9fe549ab8bc697573b468f68/rest/services/World/GeocodeServer/reverseGeocode/',
|
|
{
|
|
params: {
|
|
f: 'json', // Format JSON response
|
|
distance: 2000,
|
|
category: 'POI',
|
|
location: {
|
|
spatialReference: { wkid: 4326 },
|
|
x: longitude,
|
|
y: latitude,
|
|
},
|
|
token: apiKey.value,
|
|
},
|
|
}
|
|
)
|
|
.then((response) => {
|
|
// console.log('poi', response.data.location)
|
|
poiPlaceName.value = response.data.address
|
|
? response.data.address.PlaceName === ''
|
|
? response.data.address.ShortLabel
|
|
: response.data.address.PlaceName
|
|
: 'ไม่พบข้อมูล'
|
|
const poiPoint = new Point({
|
|
longitude: response.data.location.x,
|
|
latitude: response.data.location.y,
|
|
})
|
|
const poiSymbol = {
|
|
type: 'picture-marker',
|
|
url: 'http://maps.google.com/mapfiles/ms/icons/blue.png',
|
|
width: '32px',
|
|
height: '32px',
|
|
}
|
|
const poiGraphic = new Graphic({
|
|
geometry: poiPoint,
|
|
symbol: poiSymbol,
|
|
})
|
|
mapView.graphics.add(poiGraphic)
|
|
// อัปเดตการแสดงผลให้แสดงทั้งตำแหน่งของผู้ใช้และ POI
|
|
mapView.goTo({
|
|
target: [userPoint, poiPoint],
|
|
zoom: zoomMap.value,
|
|
})
|
|
|
|
updateLocation(latitude, longitude, poiPlaceName.value)
|
|
})
|
|
.catch(async (error) => {
|
|
// console.error('Error fetching points of interest:', error)
|
|
// Get POI place ยิงไปขอที่ server arcgis ไม่ต้องใช้ token
|
|
await axios
|
|
.get(
|
|
'https://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer/reverseGeocode/',
|
|
{
|
|
params: {
|
|
f: 'json', // Format JSON response
|
|
distance: 2000,
|
|
category: 'POI',
|
|
location: {
|
|
spatialReference: { wkid: 4326 },
|
|
x: longitude,
|
|
y: latitude,
|
|
},
|
|
},
|
|
}
|
|
)
|
|
.then((response) => {
|
|
// console.log('poi', response.data.location)
|
|
poiPlaceName.value = response.data.address
|
|
? response.data.address.PlaceName === ''
|
|
? response.data.address.ShortLabel
|
|
: response.data.address.PlaceName
|
|
: 'ไม่พบข้อมูล'
|
|
const poiPoint = new Point({
|
|
longitude: response.data.location.x,
|
|
latitude: response.data.location.y,
|
|
})
|
|
const poiSymbol = {
|
|
type: 'picture-marker',
|
|
url: 'http://maps.google.com/mapfiles/ms/icons/blue.png',
|
|
width: '32px',
|
|
height: '32px',
|
|
}
|
|
const poiGraphic = new Graphic({
|
|
geometry: poiPoint,
|
|
symbol: poiSymbol,
|
|
})
|
|
mapView.graphics.add(poiGraphic)
|
|
// อัปเดตการแสดงผลให้แสดงทั้งตำแหน่งของผู้ใช้และ POI
|
|
mapView.goTo({
|
|
target: [userPoint, poiPoint],
|
|
zoom: zoomMap.value,
|
|
})
|
|
|
|
updateLocation(latitude, longitude, poiPlaceName.value)
|
|
})
|
|
.catch((error) => {
|
|
// console.error('Error fetching points of interest:', error)
|
|
})
|
|
})
|
|
})
|
|
})
|
|
} catch (error) {
|
|
console.error('Error loading the map', error)
|
|
}
|
|
}
|
|
|
|
onMounted(async () => {
|
|
await initializeMap()
|
|
})
|
|
</script>
|
|
|
|
<template>
|
|
<!-- Loading skeleton -->
|
|
<div v-if="!poiPlaceName" class="col-12 ">
|
|
<q-skeleton :height="$q.screen.gt.xs? '35vh': '45px'" width="100%" :style="$q.screen.gt.xs? ';':'border-radius: 20px'" class="bg-grey-4" />
|
|
</div>
|
|
|
|
<q-card v-show="poiPlaceName" bordered flat class="col-12 bg-grey-2 shadow-0" :style="$q.screen.gt.xs? ';':'border-radius: 20px'" >
|
|
<div v-if="$q.screen.gt.xs" >
|
|
<div id="mapViewDisplay" style="height: 35vh;"></div>
|
|
|
|
<div
|
|
:class="
|
|
$q.screen.gt.xs
|
|
? 'q-pa-xs text-weight-medium text-grey-8'
|
|
: 'q-pa-xs text-weight-medium text-grey-8'
|
|
"
|
|
>
|
|
พื้นที่ใกล้เคียง
|
|
<span class="q-px-sm">:</span>
|
|
{{ poiPlaceName }}
|
|
</div>
|
|
</div>
|
|
|
|
|
|
<q-card v-else style="border-radius: 20px;">
|
|
<q-expansion-item
|
|
class="shadow-1 overflow-hidden bg-grey-4 text-left"
|
|
style="border-radius: 20px"
|
|
dense
|
|
>
|
|
<template v-slot:header>
|
|
<q-item-section avatar class="q-pr-none expanAS">
|
|
<q-avatar icon="mdi-map-marker" />
|
|
</q-item-section>
|
|
|
|
<q-item-section>
|
|
{{ poiPlaceName }}
|
|
</q-item-section>
|
|
</template>
|
|
|
|
<div id="mapViewDisplay" style="height: 20vh;"></div>
|
|
</q-expansion-item>
|
|
</q-card>
|
|
|
|
</q-card>
|
|
</template>
|
|
<style >
|
|
.expanAS.q-item__section--avatar{
|
|
min-width: 40px !important;
|
|
}
|
|
</style>
|