封面图片引用自www.haulmont.com
一、功能概述
图层是地理信息系统的基本信息要素,是地理信息主要载体之一。通常一个系统中包含不同专题数据的图层,对这些图层的控制在系统可以说是必备的功能。可能地理信息的初学者先接触到的是ESRI的ArcMap,里面的图层管理提供了丰富的图层数据操作相关的功能。而在Web系统中大部分系统图层的功能都如下面Google Earth中的按资源目录组织图层控制入口,实现图层的显示与隐藏。
二、实现思路
图层描述图片引用自www.haulmont.com
图层控制的实现关键点我认为主要有以下两个:
1) 图层与控件关联
图层在加载前或后,需要与最终交互的控件关联。最终交互的控件根据具体的需求可以是Button,Link,Tree或者Menu等常见控件。最终要的关联是指通过图层Id,变量本身等将控件操作能找到对应的图层。根据具体的程序设计这个关联方式可以很自由,只要能让控件操作能找到对于的图层做正确的响应就行。在复杂的场景下,这部分设计还是挺重要的。
2) 图层本身的显示与隐藏的设定
显示隐藏对用户而言,只是图层是否可见。图层可见与不可见在程序中可以有两个方式实现:
- 图层保持加载成功后,通过相应的属性与方法将图层设置为隐藏。有的是SDK中可能是图层对象的一个值类型为Boolean的属性,或者是一个方法。这种方式的优点是切换过程不会有明显的图层重载过程,Leaflet实现图层显示与隐藏稍微有所不同,以 TileLayer 为例子,显示隐藏图片通过Layer容器的样式控制
display属性来控制,不论是通过修改style或者class的。
2. 显示时,加载图层;隐藏时,移除图层。这种方式通常是可以解决数据量较大时,图层加载后造成长时间大量的内存高占用。缺点是每次显示时都需要重新加载数据,重新加载的过程可能对用户体验是一个挑战,特别是在大量的矢量数据的场景。因此,通常在特定的场景下使用。
三、代码实现
代码还是在之前的仓库,预览时需要访问本地地址的路由 http://localhost:8080/#/layercontrol。关于图层加载的方法实现可以参考之前的文章,或者 src/utils/map.js中查看。
// src/views/LayerControl.vue
<template>
<div class="page-container">
<div class="layer-container">
<div class="layer-container__item">
<input
type="checkbox"
name="openstreetmap"
v-model="isShowOpenstreetMap"
@change="changeOpenStreetMapByStyle"
/>
<label for="openstreetmap">OpenStreet Map Layer</label><br />
</div>
<div class="layer-container__item">
<input
type="checkbox"
name="acgislayer"
v-model="isShowArcGisLayer"
@change="changeArcGisLayer"
/>
<label for="acgislayer">ArcGIS Layer</label>
</div>
</div>
<div id="map-container"></div>
</div>
</template>
<script>
export default {
name: 'mapView',
components: {},
data() {
return {
map: null,
OSMUrl: 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
tileLayer:
'https://services.arcgisonline.com/ArcGIS/rest/services/USA_Topo_Maps/MapServer',
isShowOpenstreetMap: true,
openstreetMap: null,
isShowArcGisLayer: false,
arcGisLayer: null
}
},
async mounted() {
this.map = this.$utils.map.createMap('map-container')
this.openstreetMap = await this.$utils.map.createTileLayer(
this.map,
this.OSMUrl,
{}
)
this.map.setView([38.369572, -97.681121, -0.09], 13)
},
methods: {
// 通过style属性显示隐藏
changeOpenStreetMapByStyle(event) {
const layerContaier = this.openstreetMap.getContainer()
layerContaier.style.display = event.target.checked ? 'block' : 'none'
},
// 通过class属性显示隐藏
changeOpenStreetMapByClassName(event) {
const layerContaier = this.openstreetMap.getContainer()
event.target.checked
? (layerContaier.className = layerContaier.className.replace(
'hideLayer',
''
))
: (layerContaier.className = layerContaier.className + ' hideLayer')
},
// 通过加载图层和移除图层实现显示与隐藏
changeArcGisLayer(event) {
event.target.checked ? this.addArcGisLayer() : this.removeArcgisLayer()
},
async addArcGisLayer() {
this.arcGisLayer = await this.$utils.map.addEsirTiledMapLayer(this.map, {
url: this.tileLayer,
maxZoom: 15
})
this.arcGisLayer.bringToFront()
},
async removeArcgisLayer() {
this.arcGisLayer.remove()
}
}
}
</script>
<style lang="less">
.page-container {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
display: flex;
.layer-container {
width: 320px;
height: 100%;
background-color: #efefef;
&__item {
margin: 10px 0;
text-align: left;
padding: 10px;
background-color: #fefefe;
}
}
#map-container {
flex: 1;
height: 100%;
}
.hideLayer {
display: none;
}
}
</style>
四、总结
Web端的地图Library可以选择的不小,比如openlayers, mapbox, arcgis api for javascript 或者国产的SupperMap。各国厂商的实现方法不尽相同,因此重要的是了解功能实现的原理,这样才能举一反三,切换技术方案时就很轻松。
目录
(一) Vue-CLI and Leaflet:起步 - 在 Vue-CLI 中使用 Leaflet
(二) Vue-CLI and Leaflet:地图基本操作(放大,缩小,平移,定位等)
(三) Vue-CLI and Leaflet: 添加 marker, polyline, polygon
(四) Vue-CLI and Leaflet: 添加 tooltips 和 popup
(七) Vue-CLI and Leaflet: 面 绘 制
(八) Vue-CLI and Leaflet :加载 Esri ArcGIS Map Service
(九) Vue-CLI and Leaflet: 图层控制基本功能的实现
(十) Vue-CLI and Leaflet: AGS 属性查询与点图查询
(十一)Vue-CLI and Leaflet: 点聚合 Leaflet.markercluster
源码请参看 我的GitHub,由于文章是一边coding,一边写的所以 Github 里面的源码可能有点乱,可以根据功能来找对应的代码。后面会陆续整理完善。