一柏副、本文簡介
鼠標(biāo)在地圖上點擊會出現(xiàn)一個彈窗,并且出現(xiàn)在鼠標(biāo)指針上方道川。
如果在地圖邊緣點擊午衰,會保證彈窗能完整顯示出來,所以會稍微移動底圖冒萄。
二臊岸、開發(fā)環(huán)境
Vite + Vue3 + ol6
# 1、使用 Vite 創(chuàng)建項目尊流;取個好聽的項目名帅戒;拉取 vue 的代碼模板
npm init vite@latest
# 2、初始化項目
cd you-project
npm install
# 3、安裝 ol
npm i ol -S
# 4逻住、啟動項目
npm run dev
使用 Vite
初始化項目并安裝 ol
钟哥,更詳細(xì)做法可以查看 『Vite + Vue3 + OpenLayers 起步』
三、思路與編碼
思路
- 初始化地圖
- 地圖點擊事件瞎访,并獲取當(dāng)前點擊的坐標(biāo)位置
- 彈出窗口
初始化地圖
初始化地圖詳細(xì)操作可以查看 『Vite + Vue3 + OpenLayers 起步』
- 要初始化地圖腻贰,首先需要引入
ol
提供的基礎(chǔ)服務(wù) - 還需要一個地圖容器(我使用的是一個
div
標(biāo)簽) - 然后通過
ol
提供的方法綁定這個容器 - 配置基礎(chǔ)參數(shù),渲染地圖
地圖點擊事件
ol
提供了一系列的交互事件扒秸,其中就有 鼠標(biāo)點擊底圖 事件利用這個事件獲取到當(dāng)前點擊的坐標(biāo)位置
彈出窗口
彈窗需要一個容器來展示信息(我使用了一個
div
標(biāo)簽)通過"地圖點擊事件“獲取到的坐標(biāo)位置來定位彈窗出現(xiàn)的位置
本例使用了 ol
提供的方法播演,把 彈窗容器 放入 ol的“覆蓋物”’ 中管理。
彈窗展示了現(xiàn)在所點擊的坐標(biāo)軸信息伴奥,還有一個關(guān)閉按鈕写烤。
編碼
<template>
<!-- 地圖容器 -->
<div id="map" class="map__x" ref="mapCom"></div>
<!-- 彈窗容器 -->
<div ref="popupCom" class="popup">
<!-- 關(guān)閉按鈕 -->
<span class="icon-close" @click="closePopup">?</span>
<!-- 彈窗內(nèi)容(展示坐標(biāo)信息) -->
<div class="content">{{currentCoordinate}}</div>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import { Map, View } from 'ol' // 引入容器綁定模塊和視圖模塊
import Tile from 'ol/layer/Tile' // 瓦片加載器
import XYZ from 'ol/source/XYZ' // 引入XYZ地圖格式
import Overlay from 'ol/Overlay'// 引入覆蓋物模塊
import 'ol/ol.css' // ol提供的css樣式(必須引入)
const mapCom = ref(null) // 地圖容器
const popupCom = ref(null) // 彈窗容器
const map = ref(null) // 地圖實例
const overlay = ref(null) // 覆蓋物實例
const currentCoordinate = ref('') // 彈窗信息
// 初始化地圖
function initMap() {
// 注冊一個覆蓋物
overlay.value = new Overlay({
element: popupCom.value, // 彈窗標(biāo)簽,在html里
autoPan: true, // 如果彈窗在底圖邊緣時拾徙,底圖會移動
autoPanAnimation: { // 底圖移動動畫
duration: 250
}
})
map.value = new Map({
target: mapCom.value,
layers: [
new Tile({ // 加載瓦片
name: 'defaultLayer',
source: new XYZ({ // 瓦片底圖地址
url: 'http://map.geoq.cn/ArcGIS/rest/services/ChinaOnlineStreetPurplishBlue/MapServer/tile/{z}/{y}/{x}'
})
})
],
view: new View({
projection: 'EPSG:4326', // 投影坐標(biāo)系
center: [113.1206, 23.034996], // 地圖中心點
zoom: 12 // 地圖縮放級別(打開頁面時默認(rèn)級別)
}),
overlays: [overlay.value] // 綁定一個覆蓋物
})
mapClick() // 在地圖初始化完成后再綁定點擊事件
}
// 點擊地圖事件
function mapClick() {
map.value.on('singleclick', evt => { // 綁定一個點擊事件
const coordinate = evt.coordinate // 獲取坐標(biāo)
currentCoordinate.value = coordinate // 保存坐標(biāo)點
overlay.value.setPosition(coordinate) // 設(shè)置覆蓋物出現(xiàn)的位置
})
}
// 關(guān)閉彈窗
function closePopup () {
overlay.value.setPosition(undefined) // setPosition 傳入undefined會隱藏彈窗元素
currentCoordinate.value = '' // 把彈窗內(nèi)容清空
}
onMounted(() => {
// 在元素加載完之后再執(zhí)行地圖初始化
initMap()
})
</script>
<style lang="scss" scoped>
.map__x {
width: 600px;
height: 600px;
border: 1px solid #eee;
}
.popup {
width: 300px;
height: 100px;
background: #fff;
position: absolute;
top: -115px;
left: -150px;
box-sizing: border-box;
padding: 10px;
&::after {
content: '';
display: block;
position: absolute;
width: 20px;
height: 20px;
background: #fff;
bottom: -10px;
left: 50%;
transform: translateX(-50%) rotate(45deg);
}
.icon-close {
position: absolute;
top: 0px;
right: 8px;
cursor: pointer;
}
.content {
margin-top: 14px;
}
}
</style>