An overview,

This article introduces how to add ESRI’s ArcGIS Map Service in VUE-CLI project. I believe that those who need ArcGIS Map Service have some understanding of ArcGIS platform.

Here, the function of loading ArcGIS Map Service is based on Leaflet.js. In addition to leaflet.js library, it is also necessary to use esRI extended library based on Leaflet. js implementation provided by ESRI. Based on the leaflet.js ecosystem, ESRI ADAPTS a large number of functions used to support ArcGIS platform related services, such as map service, geographic processing service, geocoding, path analysis and other functions.

This article mainly introduces the loading methods of various ArcGIS layers, including base layer, dynamic layer, image layer, tile layer, element layer, aggregation layer and thermal map.

Two, code implementation

1) Code overview and related references

All the code was added based on the directory structure built in the first article, see Vue-CLI and Leaflet (1) : Show a map

For the implementation of the function, please refer to my GitHub source code.

The ESRI-Leaflet is first installed in the project

npm install esri-leaflet --save
Copy the code

Next, start to implement the layer add function in turn.

Look at the code in the main view below, where the component Layers is the layer switch for demonstration purposes

// src\views\ArcgisServices.vue

<template>
  <div class="map-container">
    <div id="map-container"></div>
    <Layers
      @basemapLayer="addBaselayer"
      @tiledMapLayer="addTilelayer"
      @dynamicMapLayer="addDynamiclayer"
      @imageMapLayer="addImageLayer"
      @featureLayer="addFeaturelayer"
      @clusterLayer="addClusterLayer"
      @heatMap="addHeatmap"
    ></Layers>
  </div>
</template>

<script>
import Layers from "@/components/Layers.vue";

export default {
  name: "mapView",
  components: { Layers },
  data() {
    return {
      map: null,
      layers: [],
      OSMUrl: "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
      tileLayer:
        "https://services.arcgisonline.com/ArcGIS/rest/services/USA_Topo_Maps/MapServer",
      featureLayer:
        "http://sampleserver6.arcgisonline.com/arcgis/rest/services/Hurricanes/MapServer/0/",
      dynamicLayer:
        "http://sampleserver6.arcgisonline.com/arcgis/rest/services/Hurricanes/MapServer/",
      imageLayer:
        "https://landsat.arcgis.com/arcgis/rest/services/Landsat/PS/ImageServer"
    };
  },
  async mounted() {
    this.map = this.$utils.map.createMap("map-container", {
      maxZoom: 20
    });
  },
  methods: {
    clearLyrs() {
      this.layers.map(lyr => {
        lyr.remove();
      });
      this.layers = [];
    },
    async addBaselayer() { this.clearLyrs(); This. Map. SetView ([22.302437935904464, 114.17198181152345], 8);let layer1 = await this.$utils.map.addEsirBasemap(this.map, "DarkGray");
      let layer2 = await this.$utils.map.addEsirBasemap(
        this.map,
        "TerrainLabels"
      );

      this.layers.push(layer1, layer2);
    },
    async addTilelayer() { this.clearLyrs(); This. Map. SetView ([38.369572, 97.681121], 12);let layer = await this.$utils.map.addEsirTiledMapLayer(this.map, {
        url: this.tileLayer,
        maxZoom: 15
      });
      this.layers.push(layer);
    },
    async addDynamiclayer() { this.clearLyrs(); This. Map. SetView ([18.930362, 28.243945], 2);let layer = await this.$utils.map.addEsirDynamicMapLayer(this.map, {
        url: this.dynamicLayer
      });
      this.layers.push(layer);
    },
    async addImageLayer() {
      this.clearLyrs();

      let layer = await this.$utils.map.addImageMaplayer(this.map, {
        url: this.imageLayer
      });
      this.layers.push(layer);
    },
    async addFeaturelayer() { this.clearLyrs(); This. Map. SetView ([18.930362, 28.243945], 2);let layer = await this.$utils.map.addEsirFeatureLayer(this.map, {
        url: this.featureLayer
      });
      this.layers.push(layer);
    },
    async addClusterLayer() {
      this.clearLyrs();

      letself = this; This. Map. SetView ([18.930362, 28.243945], 2);let layer1 = await this.$utils.map.addEsirBasemap(this.map, "DarkGray");

      let layer2 = await this.$utils.map.addEsirClusterLayer(this.map, {
        url: this.featureLayer,
        // Cluster Options
        polygonOptions: {
          color: "#2d84c8"
        },
        // Feature Layer Options
        pointToLayer: function(geojson, latlng) {
          return self.$utils.map.createCircleMaker(latlng, 10, {
            color: "#2D84C8"}); }}); this.layers.push(layer1, layer2); }, asyncaddHeatmap() { this.clearLyrs(); This. Map. SetView ([18.930362, 28.243945], 2);let layer1 = await this.$utils.map.addEsirBasemap(this.map, "DarkGray");

      let layer2 = await this.$utils.map.addEsriHeatmap(this.map, {
        url: this.featureLayer,
        radius: 12,
        minOpacity: 1,
        blur: 50,
        gradient: { 1: "red"And 0.65:"lime"Zero:"blue"}}); this.layers.push(layer1, layer2); }}}; </script> <style lang="less">
.map-container {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;

  #map-container {
    width: 100%;
    height: 100%;
  }
}
</style>


Copy the code

Components in the Layers:

// src\components\Layers.vue

<template>
  <div class="map-layers">
    <ul>
      <li @click="$emit('basemapLayer')">basemapLayer</li>
      <li @click="$emit('tiledMapLayer')">tiledMapLayer</li>
      <li @click="$emit('dynamicMapLayer')">dynamicMapLayer</li>
      <li @click="$emit('imageMapLayer')">imageMapLayer</li>
      <li @click="$emit('featureLayer')">featureLayer</li>
      <li @click="$emit('clusterLayer')">clusterLayer</li>
      <li @click="$emit('heatMap')">heatmap</li>
    </ul>
  </div>
</template>

<script>
export default {
  name: "map-layers".data() {
    return {
      activeTool: ""
    };
  },
  methods: {
    point() {
      if(this.activeTool ! = ="point") {
        this.activeTool = "point";
        this.$emit("point");
      } else {
        this.activeTool = "";
        this.$emit("end"); }},polyline() {
      if(this.activeTool ! = ="polyline") {
        this.activeTool = "polyline";
        this.$emit("polyline");
      } else {
        this.activeTool = "";
        this.$emit("end"); }},polygon() {
      if(this.activeTool ! = ="polygon") {
        this.activeTool = "polygon";
        this.$emit("polygon");
      } else {
        this.activeTool = "";
        this.$emit("end"); }}}}; </script> <style lang="less"> .map-layers { position: absolute; right: 15px; top: 15px; z-index: 999; height: 36px; Box-shadow: 0px 0px 50px 2px Rgba (0, 0, 0, 0.35); background-color:#fff;
  ul {
    display: flex;
    padding: 0;
    margin: 0;
    list-style: none;

    li {
      padding: 0 15px;
      height: 36px;
      font-size: 13px;
      line-height: 36px;
      cursor: pointer;
    }
    li.active {
      background-color: rgb(102, 156, 255);
      color: #fff;
    }
    li:hover {
      background-color: rgb(212, 224, 246);
    }
  }
}
</style>

Copy the code

Then it needs to be specially explained that esRI-Leaflet does not expose default in the map, so the correct reference method is as follows:

// src\utils\map.js

// 全部引用
import * as esri from "esri-leafle"Import {basemapLayer, featureLayer, tiledMapLayer, dynamicMapLayer, imageMapLayer} from"esri-leaflet"; // misreference import"esri-leafle"
import esri from "esri-leafle"

Copy the code

2) Base layerbasemapLayer

BasemapLayer is used to display Esri maps and attribute data at all levels around the world. There are currently 13 types of basemapLayer, as follows:

  • Streets
  • Topographic
  • NationalGeographic
  • Oceans
  • Gray
  • DarkGray
  • Imagery
  • ImageryClarity (added in 2.1.3)
  • ImageryFirefly (added in 2.2.0)
  • ShadedRelief
  • Terrain
  • USATopo (added in 2.0.0)
  • Physical (added in 2.2.0)

In addition, there are text annotation annotation layers for different base images, which can be loaded as required:

  • OceansLabels – Labels to pair with the Oceans basemap
  • GrayLabels – Labels to pair with the Gray basemap
  • DarkGrayLabels – Labels to pair with the DarkGray basemap
  • ImageryLabels – Labels including political boundaries to pair with any Imagery basemap
  • ImageryTransportation – Street map labels for pairing with any Imagery basemap
  • ShadedReliefLabels – Labels for pairing with the ShadedRelief basemap
  • TerrainLabels – Labels for pairing with the Terrain or Physical basemap

Add a base layer to map.js:

// src\utils\map.js

......

const addEsirBasemap = async (map, layerName) => {
  returnawait basemapLayer(layerName).addTo(map); }; .Copy the code

Then add ArcGIS. Vue to add call method:

// src\views\ArcgisServices.vue

......
methods:{
	...
    async addBaselayer() { this.clearLyrs(); This. Map. SetView ([22.302437935904464, 114.17198181152345], 8);let layer1 = await this.$utils.map.addEsirBasemap(this.map, "DarkGray");
      let layer2 = await this.$utils.map.addEsirBasemap(
        this.map,
        "TerrainLabels"); this.layers.push(layer1, layer2); },... }...Copy the code

It should be noted here that all the constructors of ArcGIS MapService are asynchronous methods. I use async and await to ensure that I can cache layers correctly. This applies to all subsequent layers.

After a successful call, you should see the following effect:

3) Tile layerstiledMapLayer, Dynamic layerdynamicMapLayer, Image layerimageMapLayer

Since these three maps are all loaded in very similar ways, they are all put together, almost the same way of loading the base layer in map.js.

The OPTS parameter is the initialization parameter of the construction layer. If necessary, refer to the API documentation on the OFFICIAL website of ESRI-LeALFET for detailed description.

Url is a mandatory parameter and must be a valid ArcGIS Map Service or Image Service

// src\utils\map.js

......

const addEsirTiledMapLayer = async (map, opts) => {
  return await tiledMapLayer(opts).addTo(map);
};

const addEsirDynamicMapLayer = async (map, opts) => {
  return await dynamicMapLayer(opts).addTo(map);
};
const addImageMaplayer = async (map, opts) => {
  returnawait imageMapLayer(opts).addTo(map); }; .Copy the code
// src\views\ArcgisServices.vue

......
methods:{
	...
	async addTilelayer() { this.clearLyrs(); This. Map. SetView ([38.369572, 97.681121]);let layer = await this.$utils.map.addEsirTiledMapLayer(this.map, {
        url: this.tileLayer,
        maxZoom: 15
      });
      this.layers.push(layer);
    },
    async addDynamiclayer() { this.clearLyrs(); This. Map. SetView ([18.930362, 28.243945], 2);let layer = await this.$utils.map.addEsirDynamicMapLayer(this.map, {
        url: this.dynamicLayer
      });
      this.layers.push(layer);
    },
    async addImageLayer() {
      this.clearLyrs();

      let layer = await this.$utils.map.addImageMaplayer(this.map, { url: this.imageLayer }); this.layers.push(layer); },... }...Copy the code

If according to the code I provided after a successful call, you can see the correct map display as follows

Tile layer tiledMapLayer

Dynamic layer dynamicMapLayer

imageMapLayer

3) Element layersfeatureLayer

3.1 Load featureLayer directly

Similarly, the OPTS parameter is the initialization parameter of the construction layer. If necessary, go to the API documentation on the official website of ESRI-LeALFET for detailed description. Url must be included in the required parameters, and the URL must be a valid ArcGIS Map Service Feature Layer

// src\utils\map.js

......

const addEsirFeatureLayer = async (map, opts) => {
  returnawait featureLayer(opts).addTo(map); }; .Copy the code
// src\views\ArcgisServices.vue

......
methods:{
	...    

async addFeaturelayer() { this.clearLyrs(); SetView ([18.930362, -28.243945], 2); this.map.setView([18.930362, -28.243945], 2);let layer = await this.$utils.map.addEsirFeatureLayer(this.map, { url: this.featureLayer }); this.layers.push(layer); }... }...Copy the code

The layer loading method has been successfully called and you should see the following screen (bottomless)

3.2 Display the original featureLayer layout

After the layer result loaded in the previous step, it will be seen that the icon of the point element layer is the default icon in the leaflet. According to the official description of ESRI-Leaflet, if you want to load the layer with the configured style, you need to use a plug-in esrileaflet-render

npm install esri-leaflet-renderers --save
Copy the code

Then reference it to map.js, and after the correct and successful reference, you should see the following layer style:

// src\utils\map.js ...... // Import is referenced after the leaflet, esri-leallet reference succeeds"esri-leaflet-renderers"; .Copy the code

3.3 Customizing icon Styles

In addition to using the default ICONS and styles configured for the display layer, the Feature Layer also provides an interface for customizing icon styles.

The pointToLayer interface will return the geoJSON and latLNG of the point elements contained in the layer, from which point elements such as marker or cirlcle maker can be constructed and returned as the return value.

One thing to note here is that the interface for customizing ICONS will be automatically disabled if you refer to the plugin in 3.2 to display the layer configuration.

// for point GeoJSON, Leafet expects custom panes to be returned in pointToLayer()

 featureLayer({
    url: blockPointsUrl,
    pointToLayer: function (geojson, latlng) {
      // return $L.circleMarker(latlng);
      return $L.marker(latlng);
    }
  }).addTo(map);

Copy the code

4) Aggregate layerscluster

Previous articles have introduced how to use Leaflet. Markercluster to realize the function of point aggregation. Esri-leaflet also supports Featurelayer based on ArcGIS MapService to realize the function of point element layer aggregation. The cluster layer of ESRI-Leaflet is also based on the plug-in layer of Leaflet. markerCluster. Therefore, esRI-leaflet-cluster, leaflet.markerCluster, should be installed at the same time before use.

npm install esri-leaflet-cluster leaflet.markercluster --save
Copy the code

However, if you want to use the cluster layer provided by ESRI-Leaflet in VUE-CLI, you cannot successfully install the official example to use it by referring to the previous way. I have tried many methods, so I looked at the source code of the plug-in and made simple modifications on the source code. SRC \utils\esri-cluster.js SRC \utils\esri-cluster.js SRC \utils\esri-cluster.js SRC \utils\esri-cluster.js The following direct use of the method.

Note the addition of esri-cluster.js to SRC \utils\ project

// src\utils\map.js. import Clusterfrom "./esri-cluster"; . const addEsirClusterLayer =async (map, opts) => {
  return awaitCluster(opts).addTo(map); }; .Copy the code
// src\views\ArcgisServices.vue

......
methods:{
	...    

async addFeaturelayer() {
      this.clearLyrs();

      letself = this; SetView ([18.930362, -28.243945], 2); this.map.setView([18.930362, -28.243945], 2);let layer1 = await this.$utils.map.addEsirBasemap(this.map, "DarkGray");

      let layer2 = await this.$utils.map.addEsirClusterLayer(this.map, {
        url: this.featureLayer,
        // Cluster Options
        polygonOptions: {
          color: "#2d84c8"
        },
        // Feature Layer Options
        pointToLayer: function(geojson, latlng) {
          return self.$utils.map.createCircleMaker(latlng, 10, {
            color: "#2D84C8"}); }}); this.layers.push(layer1, layer2); }... }...Copy the code

The correct display to see after a successful call is as follows. For additional requirements, refer to the ESRI API documentation cluster-feature-Layer

! [clusterLayer](D: Sync Files\ My Nut Cloud \2- documents \Leaflet\assets/ ClusterLayer.gif)

5) Thermal diagram layerheatmap

Similar to clusterLayer, THE HEATmap of ESRI-Leaflet thermal map layer is realized based on leaflet. heat, another Leaflet plug-in. And like ESRI-Leaflet-Cluster, when invoking this plug-in, it cannot be successfully used in the way of the official EXAMPLE code of ESRI-Leaflet according to the previous way. So, do the same with SRC \utils\esri-cluster.js from the plugin source. Install dependent plug-ins before using:

npm install esri-leaflet-heatmap leaflet-heat --save
Copy the code

Note that SRC \utils\ added this esri- Heatmap. js reference in map.js

// src\utils\map.js 

......

import Heatmap from "./esri-heatmap"; . const addEsriHeatmap = async (map, opts) => {returnawait Heatmap(opts).addTo(map); }; .Copy the code
// src\views\ArcgisServices.vue

......
methods:{
	...    

async addFeaturelayer() { this.clearLyrs(); This. Map. SetView ([18.930362, 28.243945], 2);let layer1 = await this.$utils.map.addEsirBasemap(this.map, "DarkGray");

      let layer2 = await this.$utils.map.addEsriHeatmap(this.map, {
        url: this.featureLayer,
        radius: 12,
        minOpacity: 1,
        blur: 50,
        gradient: { 1: "red"And 0.65:"lime"Zero:"blue"}}); this.layers.push(layer1, layer2); }... }...Copy the code

The correct display to see after a successful call is as follows. If you have other requirements, refer to the Esri API document Heatmap-feature-Layer.

Third, summary

In addition, there is also a VectorLayer, which is similar to Basemap and can only load layer resources provided by ESRI, and it is still in beta so I don’t think it is necessary to go further.

If the project uses ESRI ArcGIS platform, its functions are relatively complex and there is no need for 3D display, and arcGIS API for Javascript is too heavy. The combination of ESRI-Leaflet with Leaflet and its surrounding ecology is indeed a very good choice. If there is something wrong, please correct me.

directory

Vue-cli and Leaflet: Start using the Leaflet in VUe-CLI

(2) VUE-CLI and Leaflet: basic map operations (zoom in, zoom out, translation, positioning, etc.)

Vue-cli and Leaflet: Add marker, polyline, polygon

Vue-cli and Leaflet: Add tooltips and popup

Vue-cli and Leaflet: point drawing

Vue-cli and Leaflet: line drawing

(7) VuE-CLI and Leaflet: surface painting system

Vue-cli and Leaflet: Load Esri ArcGIS Map Service

(9) VUE-CLI and Leaflet: layer control implementation of basic functions

(10) VUE-CLI and Leaflet: AGS attribute query and point map query

Vue-cli and Leaflet: point aggregation leaflet. markerCluster

Please refer to my GitHub for the source code. Since the article is written at the same time as coding, the source code in GitHub may be a little confused, you can find the corresponding code according to the function. Later will be sorted out and improved.