为了页面的美观,这里我们使用的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本地部署(开发环境)

关注我! 不迷路