Vue-CLI and Leaflet (九): 图层控制基本功能的实现功能描述

2,271 阅读3分钟

封面图片引用自www.haulmont.com

一、功能概述

图层是地理信息系统的基本信息要素,是地理信息主要载体之一。通常一个系统中包含不同专题数据的图层,对这些图层的控制在系统可以说是必备的功能。可能地理信息的初学者先接触到的是ESRI的ArcMap,里面的图层管理提供了丰富的图层数据操作相关的功能。而在Web系统中大部分系统图层的功能都如下面Google Earth中的按资源目录组织图层控制入口,实现图层的显示与隐藏。

image.png

二、实现思路

1-2.jpg

图层描述图片引用自www.haulmont.com

图层控制的实现关键点我认为主要有以下两个:

1) 图层与控件关联

图层在加载前或后,需要与最终交互的控件关联。最终交互的控件根据具体的需求可以是Button,Link,Tree或者Menu等常见控件。最终要的关联是指通过图层Id,变量本身等将控件操作能找到对应的图层。根据具体的程序设计这个关联方式可以很自由,只要能让控件操作能找到对于的图层做正确的响应就行。在复杂的场景下,这部分设计还是挺重要的。

2) 图层本身的显示与隐藏的设定

显示隐藏对用户而言,只是图层是否可见。图层可见与不可见在程序中可以有两个方式实现:

  1. 图层保持加载成功后,通过相应的属性与方法将图层设置为隐藏。有的是SDK中可能是图层对象的一个值类型为Boolean的属性,或者是一个方法。这种方式的优点是切换过程不会有明显的图层重载过程,Leaflet实现图层显示与隐藏稍微有所不同,以 TileLayer 为例子,显示隐藏图片通过Layer容器的样式控制display属性来控制,不论是通过修改style或者class的。

iShot_2022-08-13_21.08.05.gif 2. 显示时,加载图层;隐藏时,移除图层。这种方式通常是可以解决数据量较大时,图层加载后造成长时间大量的内存高占用。缺点是每次显示时都需要重新加载数据,重新加载的过程可能对用户体验是一个挑战,特别是在大量的矢量数据的场景。因此,通常在特定的场景下使用。

iShot_2022-08-13_21.42.04.gif

三、代码实现

代码还是在之前的仓库,预览时需要访问本地地址的路由 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: 线 绘制

(七) 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 里面的源码可能有点乱,可以根据功能来找对应的代码。后面会陆续整理完善。