目录
一、案例截图
二、安装OpenLayers库
javascript
npm install ol
三、代码实现
覆盖物(Overlay)是用于在地图上显示额外的HTML元素,如弹出窗口、信息框、控件等的层。与图层不同,覆盖物不直接渲染地理要素,而是用于展示与地图位置相关的HTML内容。
关键参数:
**element (必需):**指定用于作为Overlay内容的DOM元素。通常是一个HTML元素,例如div,作为弹出框或工具提示等。
**autoPan (可选) :**boolean 或 { animation: { duration: number } } 默认值:false,如果设置为 true,地图将在Overlay显示时自动平移,以确保Overlay的位置始终在视图范围内。如果设置为对象,可以自定义平移时的动画效果。例如,设置动画持续时间。
position (可选) :[number, number](坐标数组) 默认值:undefined,初始化时设置Overlay的位置,指定为地图坐标系中的坐标。如果未指定,Overlay不会显示。
**stopEvent (可选) :**默认值:true,确定Overlay的点击事件是否会停止事件传播。如果设置为 false,点击 Overlay 的内容不会阻止点击事件向下传播到地图层。
**offset (可选) :**默认值:[0, 0] 说明:Overlay内容相对于指定位置的偏移量,用于微调Overlay的显示位置。例如,可以通过提供负值来向上或向左移动Overlay。
调用示例:
javascript
let overlay = new Overlay({
element: popupBox,
autoPan: {
animation: {
duration: 250,
},
},
offset:[-5,-5],
});
实现思路:
使用OpenLayers的Overlay类来实现弹出框展示信息:
1、获取DOM元素用于展示信息。
2、在地图上添加Overlay。
3、在地图上点击事件中更新弹出框位置和内容。
核心代码:
创建一个弹出框(Overlay),并将其添加到地图上。
javascript
<div id="popup-box" class="popup-box">
<button id="close-button" class="close-button">×</button>
<div id="popup-content" class="popup-content"></div>
</div>
//其他代码省略...
let popupBox = document.getElementById('popup-box');
let popupContent = document.getElementById('popup-content');
let closeButton = document.getElementById('close-button')
let overlay = new Overlay({
element: popupBox,
autoPan: {
animation: {
duration: 250,
},
},
});
this.map.addOverlay(overlay);
地图点击事件:
javascript
this.map.on('singleclick', (evt) => {
let lonLat = evt.coordinate;
popupContent.innerHTML = `<div>经度:${lonLat[0]}</div><div>纬度:${lonLat[1]}</div>`;
overlay.setPosition(lonLat);
});
关闭弹出框的事件处理:
javascript
closeButton.addEventListener('click', () => {
overlay.setPosition(undefined); // 关闭弹出框
});
完整代码:
html
<template>
<div>
<div id="map-container"></div>
<div id="popup-box" class="popup-box">
<button id="close-button" class="close-button">×</button>
<div id="popup-content" class="popup-content"></div>
</div>
</div>
</template>
<script>
import {Map,View} from 'ol'
import { transform, fromLonLat, toLonLat } from 'ol/proj';
import { toStringHDMS } from 'ol/coordinate';
import { Tile as TileLayer } from 'ol/layer'
import { get } from 'ol/proj';
import { getWidth, getTopLeft } from 'ol/extent'
import { WMTS } from 'ol/source'
import WMTSTileGrid from 'ol/tilegrid/WMTS'
import { defaults as defaultControls} from 'ol/control';
import Overlay from 'ol/Overlay';
export const projection = get("EPSG:4326");
const projectionExtent = projection.getExtent();
const size = getWidth(projectionExtent) / 256;
const resolutions = [];
for (let z = 0; z < 19; ++z) {
resolutions[z] = size / Math.pow(2, z);
}
export default {
data() {
return {
map:null,
showPopup: false,
popupPosition: { x: 0, y: 0 },
}
},
mounted(){
this.initMap() // 加载矢量底图
},
methods:{
initMap() {
const KEY = '你申请的KEY'
this.map = new Map({
target: 'map-container',
layers: [
// 底图
new TileLayer({
source: new WMTS({
url: `http://t{0-6}.tianditu.com/vec_c/wmts?tk=${KEY}`,
layer: 'vec', // 矢量底图
matrixSet: 'c', // c: 经纬度投影 w: 球面墨卡托投影
style: "default",
crossOrigin: 'anonymous', // 解决跨域问题 如无该需求可不添加
format: "tiles", //请求的图层格式,这里指定为瓦片格式
wrapX: true, // 允许地图在 X 方向重复(环绕)
tileGrid: new WMTSTileGrid({
origin: getTopLeft(projectionExtent),
resolutions: resolutions,
matrixIds: ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15','16','17','18']
})
})
}),
// 标注
new TileLayer({
source: new WMTS({
url: `http://t{0-6}.tianditu.com/cva_c/wmts?tk=${KEY}`,
layer: 'cva', //矢量注记
matrixSet: 'c',
style: "default",
crossOrigin: 'anonymous',
format: "tiles",
wrapX: true,
tileGrid: new WMTSTileGrid({
origin: getTopLeft(projectionExtent),
resolutions: resolutions,
matrixIds: ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15','16','17','18']
})
})
})
],
view: new View({
center: [113.082753,28.180449],
projection: projection,
zoom: 12,
maxZoom: 17,
minZoom: 1
}),
//加载控件到地图容器中
controls: defaultControls({
zoom: false,
rotate: false,
attribution: false
})
});
let popupBox = document.getElementById('popup-box');
let popupContent = document.getElementById('popup-content');
let closeButton = document.getElementById('close-button')
let overlay = new Overlay({
element: popupBox,
autoPan: {
animation: {
duration: 250,
},
},
});
this.map.addOverlay(overlay);
// 添加地图点击事件
this.map.on('singleclick', (evt) => {
let lonLat = evt.coordinate;
popupContent.innerHTML = `<div>经度:${lonLat[0]}</div><div>纬度:${lonLat[1]}</div>`;
overlay.setPosition(lonLat);
});
// 关闭弹出框的事件处理
closeButton.addEventListener('click', () => {
overlay.setPosition(undefined); // 关闭弹出框
});
},
}
}
</script>
<style scoped>
#map-container {
width: 100%;
height: 100vh;
}
.popup-box {
background: rgba(255, 255, 255, 0.95);
border: 1px solid #ccc;
border-radius: 8px;
padding: 20px;
z-index: 1000;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
transition: all 0.3s ease;
max-width: 300px;
font-family: 'Arial', sans-serif;
position: absolute;
transform: translate(-50%, -100%); /* 使弹出框上移并居中 */
}
/* 添加箭头样式 */
.popup-box::after {
content: "";
position: absolute;
top: 100%; /* 箭头位于弹出框的底部 */
left: 50%; /* 箭头横向居中 */
margin-left: -6px; /* 调整箭头与弹出框的间距 */
border-width: 6px; /* 箭头的大小 */
border-style: solid;
border-color: rgba(255, 255, 255, 0.95) transparent transparent transparent; /* 箭头的颜色 */
}
.close-button {
background: none;
color: gray;
border: none;
font-size: 20px;
position: absolute;
top: 10px;
right: 10px;
cursor: pointer;
}
.popup-content {
width: 240px;
margin-top: 10px;
font-size: 16px;
line-height: 1.5;
}
</style>