Vite + Vue3 + OpenLayers 弹窗
一、本文简介
鼠标在地图上点击会出现一个弹窗,并且出现在鼠标指针上方。
如果在地图边缘点击,会保证弹窗能完整显示出来,所以会稍微移动底图。
二、开发环境
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>
发表评论 (审核通过后显示评论):