❝
注:当前使用的是 ol 5.3.0 版本,天地图使用的
key
请到天地图官网申请,并替换为自己的key
地图标注是将空间位置信息点与地图关联、通过图标、窗口等形式把相关信息展现到地图上。在WebGIS
中地图标注是重要的功能之一,可以为用户提供个性化服务,如兴趣点等。地图标注表现方式有图文标注、Popup
标注、聚合标注等。本节主要介绍加载图文标注。
1. 地图标注基本原理
地图标注通过在已知坐标点添加图片、文字或者图文的方式展现内容信息。可以通过鼠标点击获取目标点位置坐标,也可以通过属性传递获取。
2. 加载地图标注
OpenLayers
地图标注由叠加类Overlay
实现,主要内容参数为HTMLElement
。示例通过document.createElement
创建标注内容。
ini
const htmlEle = document.createElement("div")
const closeEle = document.createElement('span')
const mainEle = document.createElement('div')
mainEle.className = 'ol-popup-main'
mainEle.textContent = "这是四川省"
closeEle.textContent = "x"
closeEle.className = "ol-popup-close"
htmlEle.className = "ol-popup"
htmlEle.appendChild(mainEle)
htmlEle.appendChild(closeEle)
通过map.addOverlay
加载地图标注。
php
const marker = new ol.Overlay({
id: "maker",
position: chengdu,
element: htmlEle,
offset: [0, -70], // x、y轴偏移量,正值向右向下,负值相反
positioning: 'top-center', // 定位方式,顶部居中
aotuPan: true,
autoPanMargin: 1.25,
})
marker.setProperties({ layerName: 'overlay' }) // 设置标注图层属性
map.addOverlay(marker)
3. 移除标注图层
可以根据图层名称或者传入标注图层进行移除。
arduino
function removeOverlayByName(layerName) {
const overlays = map.getOverlays().getArray()
// console.log("overlays:", overlays)
overlays.forEach(layer => {
console.log("layer.layerName:", layer.get('layerName'))
if (layer.get('layerName') === layerName) map.removeOverlay(layer)
});
}
function removeOverlayByLayer(overlay) {
map.removeOverlay(overlay)
}
4. 打开和关闭Popup
OpenLayers
中可以通过map.addOverlay
实现Popup
弹窗,在弹窗关闭之后,通过添加交互事件,在地图上点击目标要素打开Popup
。Select
类用于图层要素交互,可以通过Select.getFeatures()
方法获取被选择的要素。
arduino
function openPopup(overlay) {
map.addOverlay(overlay)
}
function selectFeature(layer) {
const selectEvt = new ol.interaction.Select({
layers: [layer], // 用于选择要素的图层
style: new ol.style.Style({
image: new ol.style.Circle({
radius: 5,
fill: new ol.style.Fill({
color: 'yellow'
}),
stroke: new ol.style.Stroke({
color: 'red'
})
})
})
})
// 激活选择事件
selectEvt.setActive(true)
map.addInteraction(selectEvt)
map.on('click', evt => {
console.log("getLayers:", map.getLayers().getArray())
const layers = map.getLayers().getArray()
layers.forEach(layer => {
const props = layer.getProperties()
if (props.layerName === "pointLayer") {
openPopup(marker)
}
})
})
}
5. 完整代码
其中libs
文件夹下的包需要更换为自己下载的本地包或者引用在线资源。
xml
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>图文标注</title>
<meta charset="utf-8" />
<script src="../libs/js/ol-5.3.3.js"></script>
<script src="../libs/js/jquery-2.1.1.min.js"></script>
<link rel="stylesheet" href="../libs/css//ol.css">
<style>
* {
padding: 0;
margin: 0;
font-size: 14px;
font-family: '微软雅黑';
}
html,
body {
width: 100%;
height: 100%;
}
#map {
position: absolute;
width: 100%;
height: 100%;
}
.ol-mouse-position {
padding: 5px;
top: 10px;
height: 40px;
line-height: 40px;
background: #060505ba;
text-align: center;
color: #fff;
border-radius: 5px;
}
.ol-popup {
position: relative;
font-size: 16px;
color: #4c4c4c;
background-color: #ddd;
border-radius: 5px;
}
.ol-popup::before {
display: block;
content: "";
width: 0;
height: 0;
border-left: 15px solid transparent;
border-right: 15px solid transparent;
border-top: 10px solid #ddd;
position: absolute;
bottom: -8px;
left: 50%;
transform: translateX(-50%);
}
.ol-popup-main {
padding: 20px;
}
.ol-popup-close {
position: absolute;
display: inline-block;
top: -6px;
right: 5px;
color: #878282b5;
font-size: 20px;
}
.ol-popup-close:hover {
cursor: pointer;
color: #0e0e0eb5;
filter: brightness(120%);
}
</style>
</head>
<body>
<div id="map" title="地图显示"></div>
</body>
</html>
<script>
//地图投影坐标系
const projection = ol.proj.get('EPSG:3857');
//==============================================================================//
//============================天地图服务参数简单介绍==============================//
//================================vec:矢量图层==================================//
//================================img:影像图层==================================//
//================================cva:注记图层==================================//
//======================其中:_c表示经纬度投影,_w表示球面墨卡托投影================//
//==============================================================================//
const TDTImgLayer = new ol.layer.Tile({
title: "天地图影像图层",
source: new ol.source.XYZ({
url: "http://t0.tianditu.com/DataServer?T=img_w&x={x}&y={y}&l={z}&tk=2a890fe711a79cafebca446a5447cfb2",
attibutions: "天地图注记描述",
crossOrigin: "anoymous",
wrapX: false
})
})
const TDTImgCvaLayer = new ol.layer.Tile({
title: "天地图影像注记图层",
source: new ol.source.XYZ({
url: "http://t0.tianditu.com/DataServer?T=cia_w&x={x}&y={y}&l={z}&tk=2a890fe711a79cafebca446a5447cfb2",
attibutions: "天地图注记描述",
crossOrigin: "anoymous",
wrapX: false
})
})
const map = new ol.Map({
target: "map",
loadTilesWhileInteracting: true,
view: new ol.View({
// center: [11421771, 4288300],
// center: [102.6914059817791, 25.10595662891865],
center: [104.0635986160487, 30.660919181071225],
zoom: 10,
worldsWrap: true,
minZoom: 1,
maxZoom: 20,
projection: "EPSG:4326"
}),
// 鼠标控件:鼠标在地图上移动时显示坐标信息。
controls: ol.control.defaults().extend([
// 加载鼠标控件
new ol.control.MousePosition()
])
})
map.addLayer(TDTImgLayer)
map.addLayer(TDTImgCvaLayer)
map.on('click', evt => {
// 输出点击坐标
console.log(evt.coordinate)
})
// 设置标注点
const chengdu = [104.0635986160487, 30.660919181071225]
// 添加点
const pointLayer = new ol.layer.Vector({
source: new ol.source.Vector({
features: [
new ol.Feature({
geometry: new ol.geom.Point(chengdu),
name: "chengdu"
})
]
}),
style: new ol.style.Style({
image: new ol.style.Circle({
radius: 5,
fill: new ol.style.Fill({
color: 'blue'
})
}),
fill: new ol.style.Fill({
color: "yellow"
})
})
})
pointLayer.setProperties({ "layerName": "pointLayer" })
map.addLayer(pointLayer)
const htmlEle = document.createElement("div")
const closeEle = document.createElement('span')
const mainEle = document.createElement('div')
htmlEle.className = "ol-popup"
mainEle.className = 'ol-popup-main'
closeEle.className = "ol-popup-close"
mainEle.textContent = "这是四川省"
closeEle.textContent = "x"
htmlEle.appendChild(mainEle)
htmlEle.appendChild(closeEle)
// 注册关闭popup事件
closeEle.addEventListener('click', evt => {
removeOverlayByName("overlay")
// removeOverlayByLayer(marker)
})
const marker = new ol.Overlay({
id: "maker",
position: chengdu,
element: htmlEle,
offset: [0, -70], // x、y轴偏移量,正值向右向下,负值相反
positioning: 'top-center', // 定位方式,顶部居中
aotuPan: true,
autoPanMargin: 1.25,
})
marker.setProperties({ layerName: 'overlay' })
map.addOverlay(marker)
selectFeature(pointLayer)
function removeOverlayByName(layerName) {
const overlays = map.getOverlays().getArray()
// console.log("overlays:", overlays)
overlays.forEach(layer => {
console.log("layer.layerName:", layer.get('layerName'))
if (layer.get('layerName') === layerName) map.removeOverlay(layer)
});
}
function removeOverlayByLayer(overlay) {
map.removeOverlay(overlay)
}
function openPopup(overlay) {
map.addOverlay(overlay)
}
/**
* pointLayer 点击监听事件
* openlayers 中要素点击事件通过ol.interaction.Select实现,
* 通过 getFeatures() 获取点击的要素
*/
function selectFeature(layer) {
const selectEvt = new ol.interaction.Select({
layers: [layer], // 用于选择要素的图层
style: new ol.style.Style({
image: new ol.style.Circle({
radius: 5,
fill: new ol.style.Fill({
color: 'yellow'
}),
stroke: new ol.style.Stroke({
color: 'red'
})
})
})
})
// 激活选择事件
selectEvt.setActive(true)
map.addInteraction(selectEvt)
map.on('click', evt => {
console.log("getLayers:", map.getLayers().getArray())
const layers = map.getLayers().getArray()
layers.forEach(layer => {
const props = layer.getProperties()
if (props.layerName === "pointLayer") {
openPopup(marker)
}
})
// 获取选择要素
// const features = selectEvt.getFeatures().getArray()
// console.log("feats:", features)
// 若点击点要素,则打开Popup
// if (features.length) {
// openPopup(marker)
// }
// 监听状态
// selectEvt.on('change:active', evt => {
// features.forEach(features.remove, features)
// })
})
}
</script>
❝
OpenLayers示例数据下载,请回复关键字:ol数据
全国信息化工程师-GIS 应用水平考试资料,请回复关键字:GIS考试
❝【GIS之路】 已经接入了智能助手,欢迎关注,欢迎提问。
欢迎访问我的博客网站-长谈GIS :
http://shanhaitalk.com
都看到这了,不要忘记点赞、收藏 + 关注 哦 !
本号不定时更新有关 GIS开发 相关内容,欢迎关注 !