^ 关注我,带你一起学GIS ^
注:当前使用的是 ol [9.2.4] 版本,天地图使用的
key
请到天地图官网申请,并替换为自己的key
1. 一些关系
1.1. Map对象
Map是OpenLayers
的核心组件,由目标容器、视图和图层等组成。在Map对象中管理图层组以及控件,凡是涉及到图层(layers)、控件(controls)以及叠加层(overlay)的操作都由Map对象完成。
1.2. View对象
View用于控制视图,如修改地图中心点、缩放级别、地图投影以及视图动画等。
1.3. Map和View的关系
Map对象用来装载地图,View对象用来显示地图,而且View对象是Map对象的属性。OpenLayers和ArcGIS API for JS一样,将地图划分为Map和View两个顶级对象。
1.4. 图层对象
OpenLayers中图层对象很多,图层还可以形成图层组,添加到地图上的对象具有层级特点,即最近添加的图层离用户最近,即图层添加越晚,显示层级越高,与CSS
属性z-index
类似。大体上可以分为矢量图层、切片图层、影像图层等几大类。详见OpenLayers 框架体系在OpenLayers中矢量图层的大致组成关系如下
几何对象->要素(要素集)->数据源->数据集geometry
->features
->source
->layer
2. 一些属性
2.1. View对象属性
multiWord
:是否启用多地图投影坐标系,默认为 false
。当设置为 true
时,可以在同一个地图中使用多个不同的投影,适用于跨越多个地区和国家的地图。
2.2. Source 对象属性
wrapX
:是否启用图层横向重复,默认为 false
。当设置为 true
,地图沿水平方向循环出现。
3. 一些方法
3.1. 获取图层方法
可以使用getAllLayers、getLayers
方法获取加载到地图中的所有图层。
// 返回从所有图层组中获取到的所有图层
map.getAllLayers()
// 返回与地图关联的图层集合(Collection)
map.getLayers()
使用getLayers()
方法获取到图层是一个集合对象,可以通过getArray()
方法将其转换为一个数组对象。
3.2. 添加图标方法
通过 `Overlay` 类添加图标
const marker = new ol.Overlay({
element: document.getElementById('markerId'),
positioning: 'center-center',
position: [4000, -3000]
});
map.addOverlay(marker);
通过 `Feature` 要素样式添加图标
const markerStyle = new ol.style.Style({
image: new ol.style.Icon(({
src: '../image/markre.png',
size: [20, 20]
}))
});
const markerSource = new ol.source.Vector({
features: [feature]
});
const markerLayer = new ol.layer.Vector({
source: markerSource,
style: markerStyle
});
map.addLayer(markerLayer);
3.3. 添加GeoJSON方法
方式一:使用url
和format
组合。
const JSON_URL = ""
const vectorSource = new ol.source.Vector({
url: JSON_URL,
format: new ol.format.GeoJSON()
})
const layer = new ol.layer.Vector({
source: vectorSource
})
方式二:使用GeoJSON属性readFeatures
方法读取JSON数据,然后赋值给数据源features
属性,features
属性类型为数组对象。
const layer = new ol.layer.Vector({
source: new ol.source.Vector({
features: (new ol.format.GeoJSON()).readFeatures(result)
})
})
注意:在OpenLayers中加载一些非标准GeoJSON
几何对象时,需要将数据格式转换为标准GeoJSON
格式。如要添加feature
或者FeatureCollection
时,数据对象缺少type
属性,则会报错,需要将每一个要素(feature)重新设置type属性,不然readFeatures
方法会报错。
features.forEach(feature => {
feature.type = "Feature"
})
const featureCollection = {
"type": "FeatureCollection",
"features": features
}
// 添加GeoJSON数据
const featureSet = new GeoJSON().readFeatures(featureCollection)
addGeoJSON2Map(featureCollection)
3.4. 添加Popup方法
信息弹窗用于显示要素信息,在OpenLayers
中并没有直接提供一个Popup类供用户使用,但是可以使用Overlay类来实现Popup弹窗效果。
/**
* 设置 Popup 信息弹窗
* @param property:要素属性
* @param popupColumns:信息弹窗字段
* @param polygon:信息弹窗几何对象
* @param map:信息弹窗显示地图
*/
export function setPopup(property, popupColumns, polygon, map) {
removeOverlayByName('overLay',map)
// 自定义popup容器
const popupDiv = document.createElement('div')
popupDiv.setAttribute('class', 'custom-popup')
// 自定义popup头部
const headerDiv = document.createElement('div')
headerDiv.setAttribute('class', 'custom-popup-header')
const titleSpan = document.createElement('span')
titleSpan.setAttribute('class', 'custom-popup-title')
titleSpan.textContent = "属性信息"
const closeSpan = document.createElement('span')
closeSpan.setAttribute('class', 'custom-popup-close')
closeSpan.textContent = "X"
headerDiv.appendChild(titleSpan)
headerDiv.appendChild(closeSpan)
// 自定义头部定位角标
const headerAngleIcon = document.createElement('span')
headerAngleIcon.setAttribute('class', 'custom-header-angle')
// 自定义popup表格
const tableEle = document.createElement('table')
tableEle.className = "popup-table"
tableEle.setAttribute('border','1')
tableEle.setAttribute('cellpadding','0')
tableEle.setAttribute('cellspacing','0')
Object.values(popupColumns).forEach((prop,index) => {
if (prop["name"] === 'id' || prop["name"] === 'import_oid') return
const trEle = document.createElement('tr')
trEle.className = 'table-tr'
const firstTdEle = document.createElement('td')
const secondTdEle = document.createElement('td')
firstTdEle.innerText = popupColumns[index].name //popupColumns[index].comment
secondTdEle.innerText = property[popupColumns[index].name] || '暂无'
trEle.appendChild(firstTdEle)
trEle.appendChild(secondTdEle)
tableEle.appendChild(trEle)
})
popupDiv.appendChild(headerAngleIcon)
popupDiv.appendChild(headerDiv)
popupDiv.appendChild(tableEle)
const extent = polygon.getExtent()
const center = getCenter(extent)
// 创建Overlay popup
const overlay = new Overlay({
id: "temp-",
position: center,
element: popupDiv,
offset: [0,20],
autoPan: false,
autoPanMargin: 1.25,
positioning: 'top-center'
})
overlay.setProperties({ layerName: "overLay" })
map.addOverlay(overlay)
// 监听popup移除事件
closeSpan.addEventListener('click',evt => {
removeOverlayByName('overLay',map)
})
}
4. 清除所有图层时的bug
对于自己封装的清除所有图层方法在使用过程中遇到了一个问题,通过遍历所有图层来移除图层对象的方式并不能起到很好的效果,不能一次性清除目标图层。
// 清除图层
const layers = map.getLayers().getArray()
layers.forEach(layer => {
const props = layer.getProperties()
if (!props.isBaseMap){
map.removeLayer(layer)
}
})
使用以下方式可以达到清除目标图层组的操作,但是不太满意。通过过滤目标图层组,然后再对目标图层组执行清除命令。
const tarLayers = layers.filter(layer => {
const props = layer.getProperties()
if (!props.isBaseMap){
return layer
}
})
tarLayers.forEach(tar => {
map.removeLayer(tar)
})
/**
* @description:清除除了底图的所有图层
* @param map:地图对象,默认为全局地图对象
*/
export function removeAllLayer(map = window._map){
// 清除图层
const layers = map.getLayers().getArray()
// layers.forEach(layer => {
// const props = layer.getProperties()
// if (!props.isBaseMap){
// map.removeLayer(layer)
// }
// })
// 为什么要下面这种才能一次性清除呢?很奇怪
const tarLayers = layers.filter(layer => {
const props = layer.getProperties()
if (!props.isBaseMap){
return layer
}
})
tarLayers.forEach(tar => {
map.removeLayer(tar)
})
console.log(tarLayers);
// 清除Overlay
const overLayers = map.getOverlays().getArray()
overLayers.forEach(overLayer => map.removeOverlay(overLayer))
}
使用getAllLayers
方法获取到图层对象进行移除可以方便解决这个问题。
const layers = map.getAllLayers()
layers.forEach(layer => map.removeLayer(layer))
5. StyleFunction 函数
样式函数具有一个feature
参数,使用样式函数可以方便处理图层标注的问题,只需要在最后返回目标央视对象即可。
style: (feature)=>{
style.setText(new Text({
font:'16px sans-serif',
text: feature.getProperties().projectName,
fill: new Fill({
color: 'rgba(0, 0, 0, 1)'
}),
// backgroundFill: new Fill({
// color: 'rgba(255, 255, 255, 1)'
// }),
stroke:new Stroke({
color:'rgba(255, 255, 255, 1)',
width:2
})
}))
return style
}
❝
OpenLayers示例数据下载,请在公众号后台回复:ol数据
全国信息化工程师-GIS 应用水平考试资料,请在公众号后台回复:GIS考试
❝
GIS之路公众号已经接入了智能助手,欢迎大家前来提问。
欢迎访问我的博客网站-长谈GIS:
http://shanhaitalk.com
都看到这了,不要忘记点赞、收藏+关注 哦!
本号不定时更新有关 GIS开发 相关内容,欢迎关注