大家好,我是考100分的小小码 ,祝大家学习进步,加薪顺利呀。今天说一说vue中使用arcgis_vue map文件,希望您对编程的造诣更进一步.
一、概述
这篇文章讲介绍如何在 Vue-CLI 工程中添加 ESRI 的地图服务 ArcGIS Map Service,相信需要用到 ArcGIS Map Service 的对 ArcGIS 平台都有一些了解。
这里我们要是实现加载 ArcGIS Map Service 功能都是基于 leaflet.js 的。除了 leaflet.js 这库,还需要用到 esri 提供的 基于 leaflet.js 实现的拓展库 esri-leaflet。配合到 leaflet.js 生态,esri 在其基础上适配了大量的用于支持 ArcGIS 平台相关的服务的功能,如 地图服务,地理处理服务,地理编码,路径分析等功能。
这篇文章主要介绍是,其中关于 ArcGIS 各类图层的加载方式,包括:底图图层,动态图层,影像图层,瓦片图层,要素图层,聚合图层,热力图。
二、代码实现
1)代码总览与相关引用说明
所有的代码都是基于第一篇文章中建好的目录结构中添加的,请参考 Vue-CLI and Leaflet (1):显示一个地图
下面对功能的实现,请参考我的 GitHub 源码。
首先在工程中安装 esri-leaflet
npm install esri-leaflet --save
接着,开始依次实现图层添加的功能。
看以下是主视图里面的代码, 其中组件 Layers 是为了方便演示做的图层开关图层开关
// 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();
let self = 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);
},
async addHeatmap() {
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", 0.65: "lime", 0: "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>
组件 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>
然后需要特别说明一下,esri-leaflet 在地图中的引用方方式, esri-leaflet 没有暴露 default ,所以正确的引用方式如下:
// src\utils\map.js
// 全部引用
import * as esri from "esri-leafle"
// 按需引用
import {
basemapLayer,
featureLayer,
tiledMapLayer,
dynamicMapLayer,
imageMapLayer
} from "esri-leaflet";
// 错误引用
import "esri-leafle"
import esri from "esri-leafle"
2)底图图层 basemapLayer
basemapLayer 是用于显示 Esri 提供的地图和属性数据, 这些底图覆盖了全世界范围的各个层级,目前的底图一共有十三种,如下:
StreetsTopographicNationalGeographicOceansGrayDarkGrayImageryImageryClarity(added in 2.1.3)ImageryFirefly(added in 2.2.0)ShadedReliefTerrainUSATopo(added in 2.0.0)Physical(added in 2.2.0)
此外,还有正针对不同底图提供的文字标注标注图层,可根据需要加载:
OceansLabels– Labels to pair with theOceansbasemapGrayLabels– Labels to pair with theGraybasemapDarkGrayLabels– Labels to pair with theDarkGraybasemapImageryLabels– Labels including political boundaries to pair with anyImagerybasemapImageryTransportation– Street map labels for pairing with anyImagerybasemapShadedReliefLabels– Labels for pairing with theShadedReliefbasemapTerrainLabels– Labels for pairing with theTerrainorPhysicalbasemap
在 map.js 中添加底图图层的加载方法:
// src\utils\map.js
......
const addEsirBasemap = async (map, layerName) => {
return await basemapLayer(layerName).addTo(map);
};
......
然后添加 ArcGIS.vue 中添加调用方法:
// 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);
},
...
}
......
这里需要注意,所有 arcgis mapservice 的构造方法都是异步方法,我在使用过程中都是用 async,await 保证能正确图层缓存图层。后面的所有图层都是如此。
调用成功之后看到的效果如下:

3)瓦片图层 tiledMapLayer,动态图层dynamicMapLayer, 影像图层 imageMapLayer
因为这三个地图加载方式都非常相似所以就放在一起讲了, 几乎都是一样的 map.js 中添加底图图层的加载方法。
其中 opts 参数是构造图层的初始化参数,根据需要去 esri-lealfet 官网 API 文档 上的查询详细描述。
参数中 url 是必须参数,且必须为有效的 ArcGIS Map Service 或 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) => {
return await imageMapLayer(opts).addTo(map);
};
......
// 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);
},
...
}
......
如果根据我提供的代码调用成功之后,你可以看到正确的地图显示效果如下
瓦片图层 tiledMapLayer

动态图层dynamicMapLayer

影像图层
imageMapLayer, 影像图加载需要一定的时间。

3)要素图层 featureLayer
3.1 直接加载 featureLayer
同样的, opts 参数是构造图层的初始化参数,根据需要去 esri-lealfet 官网 API 文档 上的查询详细描述,其中必须参数中必须包含有 url, 且此 url 必须为有效的 ArcGIS Map Service Feature Layer

// src\utils\map.js
......
const addEsirFeatureLayer = async (map, opts) => {
return await featureLayer(opts).addTo(map);
};
......
// src\views\ArcgisServices.vue
......
methods:{
...
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);
}
...
}
.......
调用图层加载方法成功你会看到的画面如下(无底图)

3.2 显示原来 featureLayer 配置的底图样式
上一步骤中加载的的图层成果之后,会看到点要素图层的图标是 leaflet 中默认图标。根据 esri-leaflet 的官方描述如果想要加载 图层原本配置好的样式需要用到一个插件 esriLeaflet-render

npm install esri-leaflet-renderers --save
然后再再 map.js 中引用,正确成功的引用之后,则会看到的图层样式如下:
// src\utils\map.js
......
// 在 leaflet, esri-leallet 引用成功之后引用
import "esri-leaflet-renderers";
......

3.3 自定义图标样式
除了使用默认图标和显示图层所配置的样式之后,feature layer 也提供了自定义图标样式的接口。

构建方法也非常简单pointToLayer 接口会返回图层中所包含点要素的 geojson 与 latlng, 根据这个来构造 marker或cirlcle maker 等点要素并将其作为返回值 return。
这里有一点需要注意,如果引用 3.2 中的插件显示图层配置的样式,自定图标的接口将自动失效。
// 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);
4)聚合图层 cluster
之前的文章有介绍过如何使用 Leaflet.markercluster 来实现点聚合的功能,esri-leaflet 也支持基于 arcgis mapservice 的 featurelayer 来实现点要素图层的聚合功能,而且esri-leaflet的 cluster 图层也是基于 Leaflet.markercluster 这个插件图层实现的。因此,在使用之前需要同时安装 esri-leaflet-cluster, Leaflet.markercluster,
npm install esri-leaflet-cluster leaflet.markercluster --save
但想要在 vue-cli 中使用 esri-leaflet 提供的 cluster 图层,直接按之前的引用方式是无法成功安装官方示例来使用的,我试过很多方法都不行,于是,我看了插件的源码,在源码上做了简单的修改。这里因为篇幅的原因,就不知将修改的源码贴出来了,请项目源码 src\utils\esri-cluster.js。下面直接讲使用方法。
注意工程中 src\utils\ 新增了这个 esri-cluster.js
// src\utils\map.js
......
import Cluster from "./esri-cluster";
......
const addEsirClusterLayer = async (map, opts) => {
return await Cluster(opts).addTo(map);
};
......
// src\views\ArcgisServices.vue
......
methods:{
...
async addFeaturelayer() {
this.clearLyrs();
let self = 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);
}
...
}
.......
调用成功之后看到的正确的显示结果如下。如果有其它需求,可查阅 esri API 文档 cluster-feature-layer


5)热力图图层 heatmap
跟 clusterLayer非常相似,esri-leaflet的 热力图图层 heatmap 是基于另一个leaflet插件 Leaflet.heat 实现的 esri-leaflet-heatmap ,并且和esri-leaflet-cluster 一样,在调用这个插件时,按照之前的方式是无法成功的按 esri-leaflet 官方示例代码的方式使用的。因此,同样的处理方法,从插件源码中修改出 src\utils\esri-cluster.js。使用前先安装依赖插件:
npm install esri-leaflet-heatmap leaflet-heat --save
注意工程中 src\utils\ 新增了这个 esri-heatmap.js ,在 map.js 引用
// src\utils\map.js
......
import Heatmap from "./esri-heatmap";
......
const addEsriHeatmap = async (map, opts) => {
return await Heatmap(opts).addTo(map);
};
......
// 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", 0.65: "lime", 0: "blue" }
});
this.layers.push(layer1, layer2);
}
...
}
.......
调用成功之后看到的正确的显示结果如下。如果有其它需求,可查阅 Esri API 文档 heatmap-feature-layer。

三、总结
除此之外,还有 vectorlayer 但这共功能跟 basemap 类似只能加载 esri 提供的图层资源,且目前仍是 beta 版的因此我觉得暂时没有必要做 更深入的研究。
如果项目使用的 esri arcgis 平台,功能相对很复杂没有三维显示的需求,且又嫌 ArcGIS API for Javascript 太重。esri-leaflet 配合到 leaflet及其周边生态确实是一个非常好的选择。如果有什么讲的错的地方,请各位指正。
目录
(一) 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 里面的源码可能有点乱,可以根据功能来找对应的代码。后面会陆续整理完善。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
转载请注明出处: https://daima100.com/13393.html