注:当前使用的是 ol 5.3.0 版本,天地图使用的
key
请到天地图官网申请,并替换为自己的key
地图标注是将空间位置信息点与地图关联、通过图标、窗口等形式把相关信息展现到地图上。在 我WebGIS
中地图标注是重要的功能之一,可以为用户提供个性化服务,如兴趣点等。地图标注表现方式有图文标注、Popup
标注、聚合标注等。本节主要介绍加载Popup标注。
1. 聚合标注基本原理
聚合标注是指在不同地图分辨率下,通过聚合方式展现标注点信息的一种方式。目的是为了减少当前视图下地图标注点的数量,提升客户端渲染速度。如果在地图上添加大量标注点,在地图缩放级别小的情况下则会出现标注点重叠的现象,影响地图表达效果,而且导致地图渲染效率低。
在OpenLayers
中提供了相应的聚合标注功能,以此提升地图渲染速度,增强用户体验。通过聚合数据源(ol.source.Cluster)
实现矢量要素聚合功能。
2. 创建聚合标注
根据左上角和右下角坐标,确定聚合范围,随机创建10000
个坐标点,实现图层聚合。通过聚合数据源distance
参数设置标注距离,图层样式style
函数,可以设置聚合标注样式。
less
/**
* 设置标注点
* @topLeft:左上角坐标
* @bottomRight:右下角坐标
*/
const topLeft = [103.45166016463192, 30.841644278727472]
const bottomRight = [104.92822262272239, 30.397796597331766]
// 创建10000个随机点
const features = []
for (let i = 0; i < 10000; i++) {
// 创建矢量数据源
const x = topLeft[0] + Math.random() * (bottomRight[0] - topLeft[0])
const y = bottomRight[1] + Math.random() * (topLeft[1] - bottomRight[1])
const coordinate = [x, y]
const feature = new ol.Feature({
geometry: new ol.geom.Point(coordinate)
})
features.push(feature)
}
const pointFeatures = new ol.source.Vector({
features: features
})
const styleCache = {}
// 创建聚合图层
const pointLayer = new ol.layer.Vector({
source: new ol.source.Cluster({
source: pointFeatures, // 聚合数据源
distance: 40 // 聚合标注距离,当标注间距小于此值时进行聚合
}),
style: (feature, resolution) => {
const size = feature.get('features').length
let style = styleCache[size]
if (!style) {
style = [
new ol.style.Style({
image: new ol.style.Circle({
radius: 10,
stroke: new ol.style.Stroke({
color: 'rgba(255,255,255,1)'
}),
fill: new ol.style.Fill({
color: '#3399CC'
})
}),
text: new ol.style.Text({
text: size.toString(),
fill: new ol.style.Fill({
color: '#fff'
})
})
})
]
styleCache[size] = style
}
return style
}
})
pointLayer.setProperties({ "layerName": "pointLayer" })
map.addLayer(pointLayer)
3. 加载和移除聚合图层
通过map.addLayer
方法加载聚合图层,map.removeLayer
方法移除聚合图层。
dart
// 添加聚合图层
document.querySelector('.add-cluster').addEventListener('click', evt => {
if (pointLayer) {
map.addLayer(pointLayer)
}
})
// 移除聚合图层
document.querySelector('.remove-cluster').addEventListener('click', evt => {
if (pointLayer) {
map.removeLayer(pointLayer)
}
})
4. 完整代码
其中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;
}
.cluster-div {
position: relative;
padding: 10px 5px;
left: 50%;
top: 20px;
transform: translateX(-50%);
width: 250px;
text-align: center;
background: #2626268a;
border-radius: 5px;
}
.cluster-btn {
border: none;
padding: 5px;
margin: 0 10px;
}
.cluster-btn:hover {
cursor: pointer;
color: #000;
font-weight: bold;
filter: brightness(150%);
}
</style>
</head>
<body>
<div id="map" title="地图显示"></div>
<div class="cluster-div">
<button class="cluster-btn add-cluster">添加聚合标注</button>
<button class="cluster-btn remove-cluster">移除聚合标注</button>
</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)
})
/**
* 设置标注点
* @topLeft:左上角坐标
* @bottomRight:右下角坐标
*/
const topLeft = [103.45166016463192, 30.841644278727472]
const bottomRight = [104.92822262272239, 30.397796597331766]
// 创建10000个随机点
const features = []
for (let i = 0; i < 10000; i++) {
// 创建矢量数据源
const x = topLeft[0] + Math.random() * (bottomRight[0] - topLeft[0])
const y = bottomRight[1] + Math.random() * (topLeft[1] - bottomRight[1])
const coordinate = [x, y]
const feature = new ol.Feature({
geometry: new ol.geom.Point(coordinate)
})
features.push(feature)
}
const pointFeatures = new ol.source.Vector({
features: features
})
const styleCache = {}
// 创建聚合图层
const pointLayer = new ol.layer.Vector({
source: new ol.source.Cluster({
source: pointFeatures, // 聚合数据源
distance: 40 // 聚合标注距离,当标注间距小于此值时进行聚合
}),
style: (feature, resolution) => {
const size = feature.get('features').length
let style = styleCache[size]
if (!style) {
style = [
new ol.style.Style({
image: new ol.style.Circle({
radius: 10,
stroke: new ol.style.Stroke({
color: 'rgba(255,255,255,1)'
}),
fill: new ol.style.Fill({
color: '#3399CC'
})
}),
text: new ol.style.Text({
text: size.toString(),
fill: new ol.style.Fill({
color: '#fff'
})
})
})
]
styleCache[size] = style
}
return style
}
})
pointLayer.setProperties({ "layerName": "pointLayer" })
map.addLayer(pointLayer)
// 添加聚合图层
document.querySelector('.add-cluster').addEventListener('click', evt => {
if (pointLayer) {
map.addLayer(pointLayer)
}
})
// 移除聚合图层
document.querySelector('.remove-cluster').addEventListener('click', evt => {
if (pointLayer) {
map.removeLayer(pointLayer)
}
})
</script>
OpenLayers示例数据下载,请回复关键字:ol数据
全国信息化工程师-GIS 应用水平考试资料,请回复关键字:GIS考试
【GIS之路】 已经接入了智能助手,欢迎关注,欢迎提问。欢迎访问我的博客网站-长谈GIS :
http://shanhaitalk.com
都看到这了,不要忘记点赞、收藏 + 关注 哦 !
本号不定时更新有关 GIS开发 相关内容,欢迎关注 !