一、本文簡介
鼠標在地圖上點擊會出現一個彈窗,並且出現在鼠標指針上方。
如果在地圖邊緣點擊,會保證彈窗能完整顯示出來,所以會稍微移動底圖。
二、開發環境
Vite + Vue3 + ol6
# 1、使用 Vite 創建項目;取個好聽的項目名;拉取 vue 的代碼模板
npm init vite@latest
# 2、初始化項目
cd you-project
npm install
# 3、安裝 ol
npm i ol -S
# 4、啓動項目
npm run dev
使用 Vite
初始化項目並安裝 ol
,更詳細做法可以查看 『Vite + Vue3 + OpenLayers 起步』
三、思路與編碼
思路
- 初始化地圖
- 地圖點擊事件,並獲取當前點擊的座標位置
- 彈出窗口
初始化地圖
初始化地圖詳細操作可以查看 『Vite + Vue3 + OpenLayers 起步』
- 要初始化地圖,首先需要引入
ol
提供的基礎服務 - 還需要一個地圖容器(我使用的是一個
div
標籤) - 然後通過
ol
提供的方法綁定這個容器 - 配置基礎參數,渲染地圖
地圖點擊事件
ol
提供了一系列的交互事件,其中就有 鼠標點擊底圖 事件利用這個事件獲取到當前點擊的座標位置
彈出窗口
彈窗需要一個容器來展示信息(我使用了一個
div
標籤)通過"地圖點擊事件“獲取到的座標位置來定位彈窗出現的位置
本例使用了 ol
提供的方法,把 彈窗容器 放入 ol的“覆蓋物”’ 中管理。
彈窗展示了現在所點擊的座標軸信息,還有一個關閉按鈕。
編碼
<template>
<!-- 地圖容器 -->
<div id="map" class="map__x" ref="mapCom"></div>
<!-- 彈窗容器 -->
<div ref="popupCom" class="popup">
<!-- 關閉按鈕 -->
<span class="icon-close" @click="closePopup">✖</span>
<!-- 彈窗內容(展示座標信息) -->
<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, // 彈窗標籤,在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', // 投影座標系
center: [113.1206, 23.034996], // 地圖中心點
zoom: 12 // 地圖縮放級別(打開頁面時默認級別)
}),
overlays: [overlay.value] // 綁定一個覆蓋物
})
mapClick() // 在地圖初始化完成後再綁定點擊事件
}
// 點擊地圖事件
function mapClick() {
map.value.on('singleclick', evt => { // 綁定一個點擊事件
const coordinate = evt.coordinate // 獲取座標
currentCoordinate.value = coordinate // 保存座標點
overlay.value.setPosition(coordinate) // 設置覆蓋物出現的位置
})
}
// 關閉彈窗
function closePopup () {
overlay.value.setPosition(undefined) // setPosition 傳入undefined會隱藏彈窗元素
currentCoordinate.value = '' // 把彈窗內容清空
}
onMounted(() => {
// 在元素加載完之後再執行地圖初始化
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>