为了页面的美观,这里我们使用的UI库为: Ant Design Vue项目源码仓库地址:https://github.com/LuckRain7/arcgis-api-for-javascript-vue
1. 首先创建工具菜单组件
创建文件 srccomponentsToolBar.vue
并通过组件通信写好对应接口
<template> <div class="toolbar"> <!-- 使用按钮组 --> <a-button-group> <!-- 地图切换按钮 --> <a-dropdown> <a-menu slot="overlay"> <a-menu-item key="1" @click="baseMapChange(1)"> 矢量 </a-menu-item> <a-menu-item key="2" @click="baseMapChange(2)"> 影像 </a-menu-item> </a-menu> <a-button type="primary"> <a-icon type="global" />底图 <a-icon type="down" /> </a-button> </a-dropdown> <!-- 地图切换按钮 END--> <a-dropdown> <a-menu slot="overlay"> <a-menu-item key="1" @click="measurement(1)"> 开始测量 </a-menu-item> <a-menu-item key="2" @click="measurement(0)"> 取消测量 </a-menu-item> </a-menu> <a-button type="primary"> <a-icon type="tool" />测量 <a-icon type="down" /> </a-button> </a-dropdown> <!-- 标绘 GO--> <a-dropdown> <a-menu slot="overlay"> <a-menu-item key="1" @click="draw('POINT')"> 点 </a-menu-item> <a-menu-item key="2" @click="draw('POLYLINE')"> 线 </a-menu-item> <a-menu-item key="3" @click="draw('POLYGON')"> 面 </a-menu-item> <a-menu-item key="4" @click="draw('CIRCLE')"> 圆形 </a-menu-item> <a-menu-item key="5" @click="draw('RECTANGLE')"> 长方形 </a-menu-item> <a-menu-item key="6" @click="draw('stop')"> 停止标绘 </a-menu-item> <a-menu-item key="7" @click="draw('delete')"> 清除标绘 </a-menu-item> </a-menu> <a-button type="primary"> <a-icon type="highlight" />标绘 <a-icon type="down" /> </a-button> </a-dropdown> <!-- 标绘 END--> <a-button type="primary" @click="showLegend"> <a-icon type="unordered-list" />图例 </a-button> <a-button type="primary" @click="showLayerList"> <a-icon type="database" />图层 </a-button> </a-button-group> </div></template><script>export default { name: "ToolBar", methods: { // 开启测量 measurement(type) { this.$emit("measurement", type); }, // 底图切换 baseMapChange(type) { this.$emit("baseMapChange", type); }, // 标绘 draw(type) { this.$emit("draw", type); }, // 显示图例 showLegend() { this.$emit("showLegend"); }, // 显示图层 showLayerList() { this.$emit("showLayerList"); }, },};</script><style lang="less">.toolbar { position: absolute; top: 80px; right: 40px; height: 40px; width: auto; z-index: 99;}</style>
在 srcApp.vue 显示页面引入,并提供组件通讯接口
<template><!-- 工具条组件 --><tool-bar @measurement="measurement" @baseMapChange="baseMapChange" @draw="draw" @showLegend="showLegend" @showLayerList="showLayerList"></tool-bar><!-- 测量组件 --><measurement :show="isShowMeasurement" @closMmeasurement="measurement"></measurement></template><script>import ToolBar from "./components/ToolBar.vue";components: { ToolBar},methods: { // 测量 measurement(type) { switch (type) { case 0: this.isShowMeasurement = false; Map.MeasurementClose(); break; case 1: this.isShowMeasurement = true; } }, /* 地图切换 */ baseMapChange(type) { Map.baseMapChange(type); }, // 标绘 draw(type) { Map.drawActive(type); },},</script>
效果图:
1. 底图切换
在 examplesrcmapinit.js 文件中添加底图切换函数
当约定的 Type = 1 时,使用 addLayer
方法添加矢量图层并移除影像图层
当约定的 Type = 2 时,使用 addLayer
方法添加影像图层并移除矢量图层
ps: addLayer
方法是对 map.addLayer()
的二次封装
baseMapChange(type) { if (type === this.baseMap.type) return; // 防止重复加载 // 添加 影像 if (type === 2) { this.addLayer( [this.baseMap.rasterMap, this.baseMap.rasterMapAnnotation], [0, 1] ); this.removeLayer(this.baseMap.vectorMap); this.baseMap.type = 2; } // 添加 矢量 else { this.addLayer(this.baseMap.vectorMap, 0); this.removeLayer([ this.baseMap.rasterMap, this.baseMap.rasterMapAnnotation, ]); this.baseMap.type = 1; }}
在 examplesrcApp.vue 中进行应用
/* 地图切换 */baseMapChange(type) { Map.baseMapChange(type);},
效果图:
2. 测量组件
这里需要在 srcmapinit.js 中加载 ArcGIS 的测量和单位模块("esri/dijit/Measurement"
、 "esri/units"
)
ps: 模块与下方的导出函数一定要一一对应
# example\src\map\init.jsloadModules( [ "esri/map", "tdlib/SDTDTLayer", "tdlib/SDRasterLayer", "tdlib/SDRSAnnoLayer", "esri/geometry/Extent", "esri/SpatialReference",+ "esri/dijit/Measurement",+ "esri/units", "dojo/parser", ], config.loadConfig) .then( ([ Map, // 地图模块 SDTDTLayer, // 山东天地图矢量地图 SDRasterLayer, // 山东天地图影像地图 SDRSAnnoLayer, // 山东天地图影像地图注记 Extent, // 范围模块 SpatialReference, // 坐标系模块+ Measurement, //测量模块+ Units, // 单位模块 Parser, // 样式解析模块 ])
并进行相关配置 examplesrcmapinit.js(以下是增量代码,不是文件中实际位置)
// 测量工具初始化this.measurement = new Measurement( { map: this.map, defaultLengthUnit: Units.KILOMETERS, defaultAreaUnit: Units.SQUARE_KILOMETERS, }, document.getElementById("measurement"));this.measurement.startup();// 关闭测量工具MeasurementClose() { this.measurement.clearResult(); // 清除地图图案 // 拿到开启的工具名称 并关闭已开启的工具 this.measurement.getTool() && this.measurement.setTool(this.measurement.getTool().toolName, false);}
创建一个用来展示测量组件 srccomponentsMeasurement.vue
<template> <div class="measurementdiv" v-show="show"> <div class="div-header"> <span class="title">测量组件</span> <span class="close" @click="close">X</span> </div> <div id="measurement"></div> </div></template><script>export default { name: "Measurement", props: { show: Boolean, }, methods: { close() { this.$emit("closMmeasurement", 0); }, },};</script>
在页面中引入 srcApp.vue
<template><!-- 测量组件 --><measurement :show="isShowMeasurement" @closMmeasurement="measurement"></measurement></template><script> methods: { // 测量 measurement(type) { switch (type) { case 0: this.isShowMeasurement = false; Map.MeasurementClose(); break; case 1: this.isShowMeasurement = true; } }, }</script>
效果图:
3. 比例尺组件
这里需要在 srcmapinit.js 中加载 ArcGIS 的比例尺模块("esri/dijit/Scalebar"
)
ps: 模块与下方的导出函数一定要一一对应
loadModules( [+ "esri/dijit/Scalebar", ], config.loadConfig) .then( ([+ Scalebar, // 比例尺模块 ])
初始化比例尺
Scalebar({ map: this.map, attachTo: "bottom-left", scalebarUnit: "metric", scalebarStyle: "line",});
4. 标绘组件
非常抱歉,写到这里时我重构了代码,大家可以去代码仓库进行查看,重构的目的是为了更加的模块化。
这里需要在 srcmapmodulesdraw.js 中加载 ArcGIS 的画图模块、点样式模块、线样式模块、填充样式模块、图形模块和图形图层模块("esri/toolbars/draw"
、"esri/symbols/SimpleMarkerSymbol"
、"esri/symbols/SimpleLineSymbol"
、"esri/symbols/SimpleFillSymbol"
、"esri/graphic"
、"esri/layers/GraphicsLayer"
)
/* * Description: 标绘工具 * Author: LuckRain7 * Date: 2020-05-07 17:05:55 */import { loadModules } from "esri-loader";import config from "../config";function drawInit() { loadModules( [ "esri/toolbars/draw", // 画图 "esri/symbols/SimpleMarkerSymbol", // 点 "esri/symbols/SimpleLineSymbol", // 线 "esri/symbols/SimpleFillSymbol", // 面 "esri/graphic", // 图形模块 "esri/layers/GraphicsLayer", // 图形图层模块 ], config.loadConfig ) .then( ([ Draw, SimpleMarkerSymbol, SimpleLineSymbol, SimpleFillSymbol, Graphic, GraphicsLayer, ]) => { this.GraphicsLayer = GraphicsLayer; this.Graphic = Graphic; this.Draw = Draw; this.SimpleMarkerSymbol = SimpleMarkerSymbol; this.SimpleLineSymbol = SimpleLineSymbol; this.SimpleFillSymbol = SimpleFillSymbol; // 添加图形图层 this.DrawGraphics = new GraphicsLayer({ id: "drawLayer" }); // 设置图层坐标系 this.DrawGraphics.SpatialReference = new this.SpatialReference({ wkid: 4490, }); // 将图层加载到地图上,图层设置为 7 this.map.addLayer(this.DrawGraphics, 7); // 实例化画图 this.draw = new Draw(this.map); //定义图形样式 this.draw.markerSymbol = new SimpleMarkerSymbol(); this.draw.lineSymbol = new SimpleLineSymbol(); this.draw.fillSymbol = new SimpleFillSymbol(); // 添加画图的监听事件 this.draw.on("draw-complete", drawEndEvent.bind(this)); } ) .catch((err) => { console.error(err); });}// 内置函数 画完后将图形加载到图形图层function drawEndEvent(evt) { //添加图形到地图 let symbol; if (evt.geometry.type === "point" || evt.geometry.type === "multipoint") { symbol = this.draw.markerSymbol; } else if (evt.geometry.type === "line" || evt.geometry.type === "polyline") { symbol = this.draw.lineSymbol; } else { symbol = this.draw.fillSymbol; } // 获取图形样式 let tx = this.Graphic(evt.geometry, symbol); // 将图形样式加载到地图上 this.DrawGraphics.add(tx);}// 设置说话图形function drawActive(type) { let tool = null; switch (type) { case "POINT": tool = "POINT"; break; case "POLYLINE": tool = "POLYLINE"; break; case "POLYGON": tool = "POLYGON"; break; case "CIRCLE": tool = "CIRCLE"; break; case "RECTANGLE": tool = "RECTANGLE"; break; case "stop": this.draw.deactivate(); // 停止画图 break; case "delete": this.draw.deactivate(); // 停止画图 this.DrawGraphics.clear(); // 清除图层 break; } if (tool !== null) { this.draw.activate(this.Draw[tool]); //激活对应的绘制工具 }}export { drawInit, drawActive };
在 导出文件中引入 srcmapindex.js
import { MeasurementClose } from "./modules/Measurement.js";// 导入标绘功能ArcGIS.prototype.drawInit = drawInit;ArcGIS.prototype.drawActive = drawActive;
在组件中使用即可
效果图:
推荐阅读
- vue + ArcGIS 地图应用系列二:加载地图
- vue + ArcGIS 地图应用系列一:arcgis api本地部署(开发环境)