大家好,我是考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 提供的地图和属性数据, 这些底图覆盖了全世界范围的各个层级,目前的底图一共有十三种,如下:
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)
此外,还有正针对不同底图提供的文字标注标注图层,可根据需要加载:
OceansLabels
– Labels to pair with theOceans
basemapGrayLabels
– Labels to pair with theGray
basemapDarkGrayLabels
– Labels to pair with theDarkGray
basemapImageryLabels
– Labels including political boundaries to pair with anyImagery
basemapImageryTransportation
– Street map labels for pairing with anyImagery
basemapShadedReliefLabels
– Labels for pairing with theShadedRelief
basemapTerrainLabels
– Labels for pairing with theTerrain
orPhysical
basemap
在 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
接口会返回图层中所包含点要素的 geojso
n 与 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
![clusterLayer](D:\Sync Files\我的坚果云\2-文档\Leaflet\assets/clusterLayer.gif)
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