ArcGIS在VUE框架中的构建思想

项目快要上线了,出乎意料的有些空闲时间。想着就把其他公司开发的一期代码里面,把关于地图方面的代码给优化一下。试运行的时候,客户说控制台有很多飘红的报错,他们很在意,虽然很不情愿,但能改的就给改了吧。

代码框架

使用的是VUE框架, vue 2.x 版本的,使用vue-cli脚手架进行搭建的。在package.json中,arcgis的版本为"@arcgis/core": "^4.23.1"

使用到的第三方库

javascript 复制代码
  "dependencies": {
    "@arcgis/core": "^4.23.1",
    "axios": "0.18.1",
    "core-js": "3.6.5",
    "echarts": "^4.5.0",
    "echarts-gl": "1.0.0-beta.6",
    "echarts-liquidfill": "^2.0.6",
    "element-ui": "2.15.7",
    "events": "^3.3.0",
    "js-cookie": "2.2.0",
    "lodash": "^4.17.21",
    "moment": "^2.29.1",
    "normalize.css": "7.0.0",
    "nprogress": "0.2.0",
    "path-to-regexp": "2.4.0",
    "qrcodejs2": "^0.0.2",
    "screenfull": "^4.2.1",
    "vue": "2.6.10",
    "vue-i18n": "^8.18.2",
    "vue-router": "3.0.6",
    "vuex": "3.1.0"
  },
  "devDependencies": {
    "@vue/cli-plugin-babel": "4.4.4",
    "@vue/cli-plugin-eslint": "4.4.4",
    "@vue/cli-service": "4.4.4",
    "autoprefixer": "9.5.1",
    "babel-eslint": "10.1.0",
    "babel-plugin-dynamic-import-node": "2.3.3",
    "chalk": "2.4.2",
    "connect": "3.6.6",
    "eslint": "6.7.2",
    "eslint-plugin-vue": "6.2.2",
    "html-webpack-plugin": "3.2.0",
    "mockjs": "1.0.1-beta3",
    "runjs": "4.3.2",
    "sass": "1.26.8",
    "sass-loader": "8.0.2",
    "script-ext-html-webpack-plugin": "2.1.3",
    "serve-static": "1.13.2",
    "svg-sprite-loader": "4.1.3",
    "svgo": "1.2.2",
    "vue-template-compiler": "2.6.10"
  }

地图封装

将ArcGIS封装成一个组件,专门用来加载地图,一些事件分发处理。

DOM

javascript 复制代码
<template>
  <div style="width:100%;height:100%">
    <div id="map"  :style="sty">
    
    </div>
  </div>
</template>

Style

javascript 复制代码
#map {
  height: calc(100vh);
}

事件注册

在main.js中需要进行一个事件总线的注册

javascript 复制代码
Vue.prototype.$mapEventBus = new Vue()

然后在utils文件夹中创建一个文件,专门放置一些用得到的事件。比如这个文件名称为mapEvent.js

javascript 复制代码
export default {
  cleanOverlay: 'cleanOverlay',
  hideDike: 'hideDike',
  showDikes: 'showDikes',
  showBillboard: 'showBillboard',
  /** 改变图层可见性 */
  changeLayerVisible: 'changeLayerVisible'
}

这里面就是一些事件类型,比如清除,隐藏堤坝,显示堤坝,显示广告牌,改变图层可见性等等。

然后在封装的时候引入这个文件。

javascript 复制代码
import mapEvent from '@/utils/mapEvent'

当后续想添加事件,统一名称就行,不用来回在用到的地方去改字符串了。最好能从名称看出用途。随后就是对事件总线进行事件注册和监听。

javascript 复制代码
      this.$mapEventBus.$on(mapEvent.cleanOverlay, (data) => {
        // 执行某些方法
      })

      this.$mapEventBus.$on(mapEvent.hideDike, (data) => {
        // 执行某些方法
      })

      this.$mapEventBus.$on(mapEvent.showDikes, (data) => {
        // 执行某些方法
      })

      this.$mapEventBus.$on(mapEvent.showBillboard, (data) => {
        // 执行某些方法
      })

当这些注册好之后,只要有其他页面,使用emit进行事件发送,那么就能拿到传递的data参数,再去执行对应的代码逻辑。某个页面触发hideDike和showBillboard为例。

javascript 复制代码
this.$mapEventBus.$emit(mapEvent.hideDike)
javascript 复制代码
this.$mapEventBus.$emit(mapEvent.showBillboard, ['layer', 78, 'rain'])

场景View

地图该有的事件总线注册完毕之后,就可以开始创建地图了,首先引入Map对象,创建一个地图对象。再根据需要的场景,创建对应的视图View,平面2D和立体3D是有不同的View对象的。

javascript 复制代码
import Map from '@arcgis/core/Map'
import SceneView from "@arcgis/core/views/SceneView";
import MapView from "@arcgis/core/views/MapView";

const m = new Map({
    ground: "world-elevation",
    basemap: "topo-vector"
})

        // 3D场景的话,使用SceneView
        scene= new SceneView({
          container: 'map',
          map: m,
          zoom: 9,
          center:  [中心坐标值, 中心坐标值],
        })
        // 普通地图场景的话使用MapView
        view= new MapView({
          container: 'map',
          map: m,
          zoom: 10,
          center:  [中心坐标值, 中心坐标值],
        })

图层加载

地图map创建好之后,开始为地图设置对应显示的layer。这里以天地图为例,图层类型有很多种,很多配置都是相同唯独一些type值不同,因此封装成一个方法function。下面的示例是加载WebTileLayer的一些简易封装配置,将其写在tdt.js中。wkid为参考坐标系,ArcGIS的官网有对这个值的解释,有特殊坐标系的场景,或者百度坐标系高德坐标系,这些值可能都需要更改。

切片信息可以单独写在一个js文件中tdtconfig.js,与tdt.js同级目录

javascript 复制代码
export default {
  tileInfo: {
    rows: 256,
    cols: 256,
    origin: {
      x: -20037508.342787,
      y: 20037508.342787,
    },
    compressionQuality: 0,
    spatialReference: {
      wkid: 102113
    },
    lods: [
      {
        endTileCol: 31,
        endTileRow: 31,
        level: 5,
        resolution: 4891.96981024998,
        scale: 18489297.737236,
        startTileCol: 0,
        startTileRow: 0,
      },
      {
        endTileCol: 63,
        endTileRow: 63,
        level: 6,
        resolution: 2445.98490512499,
        scale: 9244648.868618,
        startTileCol: 0,
        startTileRow: 0,
      },
      {
        endTileCol: 127,
        endTileRow: 127,
        level: 7,
        resolution: 1222.992452562495,
        scale: 4622324.434309,
        startTileCol: 0,
        startTileRow: 0,
      },
      {
        endTileCol: 255,
        endTileRow: 255,
        level: 8,
        resolution: 611.4962262812475,
        scale: 2311162.2171545,
        startTileCol: 0,
        startTileRow: 0,
      },
      {
        endTileCol: 511,
        endTileRow: 511,
        level: 9,
        resolution: 305.74811314062373,
        scale: 1155581.10857725,
        startTileCol: 0,
        startTileRow: 0,
      },
      {
        endTileCol: 1023,
        endTileRow: 1023,
        level: 10,
        resolution: 152.87405657031186,
        scale: 577790.554288625,
        startTileCol: 0,
        startTileRow: 0,
      },
      {
        endTileCol: 2047,
        endTileRow: 2047,
        level: 11,
        resolution: 76.43702828515593,
        scale: 288895.2771443125,
        startTileCol: 0,
        startTileRow: 0,
      },
      {
        endTileCol: 4095,
        endTileRow: 4095,
        level: 12,
        resolution: 38.218514142577966,
        scale: 144447.63857215625,
        startTileCol: 0,
        startTileRow: 0,
      },
      {
        endTileCol: 8191,
        endTileRow: 8191,
        level: 13,
        resolution: 19.109257071288983,
        scale: 72223.81928607813,
        startTileCol: 0,
        startTileRow: 0,

      },
      {
        endTileCol: 16383,
        endTileRow: 16383,
        level: 14,
        resolution: 9.554628535644492,
        scale: 36111.909643039064,
        startTileCol: 0,
        startTileRow: 0,
      },
      {
        endTileCol: 32767,
        endTileRow: 32767,
        level: 15,
        resolution: 4.777314267822246,
        scale: 18055.954821519532,
        startTileCol: 0,
        startTileRow: 0,
      },
      {
        endTileCol: 65534,
        endTileRow: 65534,
        level: 16,
        resolution: 2.388657133911123,
        scale: 9027.977410759766,
        startTileCol: 0,
        startTileRow: 0,
      },
      {
        endTileCol: 131069,
        endTileRow: 131069,
        level: 17,
        resolution: 1.1943285669555614,
        scale: 4513.988705379883,
        startTileCol: 0,
        startTileRow: 0,
      },
      {
        endTileCol: 262138,
        endTileRow: 262138,
        level: 18,
        resolution: 0.5971642834777807,
        scale: 2256.9943526899415,
        startTileCol: 0,
        startTileRow: 0,
      }
    ]
  },
}

然后在tdt.js中引入这个切片信息配置。

javascript 复制代码
import WebTileLayer from "@arcgis/core/layers/WebTileLayer";
import SpatialReference from "@arcgis/core/geometry/SpatialReference";
import Extent from "@arcgis/core/geometry/Extent";
import tileInfo from './tdtconfig';

function tdtLayer(type,visible){
  const url = `http://t0.tianditu.gov.cn/${type}_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=${type}&STYLE=default&TILEMATRIXSET=w&TILEMATRIX={level}&TileRow={row}&TileCol={col}&format=tiles&tk=${天地图的token}`;
  const tiledLayer = new WebTileLayer({
    urlTemplate: url,
    subDomains: ["t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7"],
    spatialReference: new SpatialReference({
      wkid: 102113,
    }),
    fullExtent: new Extent({
      xmax: 20038088.3427892,
      xmin: -20038088.3427892,
      ymax: 20038088.3427892,
      ymin: -20038088.3427892,
      spatialReference: {wkid: 102113}

    }),
    initialExtent: new Extent({
      xmax: 13211664.142019678,
      xmin: 13077211.409266088,
      ymax: 2843822.418908416,
      ymin: 2810801.622689228,
      spatialReference: {wkid: 102113}
    }),
    tileInfo: tileInfo.tileInfo,
    visible
  });
  return tiledLayer;
}

export {
  tdtLayer,
}

在正式使用的时候,引入这个tdt.js文件,使用其中的tdtLayer方法。可以通过传递不同的字符串,去加载不同类型的图层。比如vec,cva,img,cia,ter,cta。通过visible的布尔类型值,控制加载时的显示与隐藏。还可以考虑增加一个参数,来控制是否需要设置透明度opacity。

在原先他们一期的项目中,是没有多加visible的,他们在创建完成之后,手动设置layer.visible的值为false。其实这个可以在创建layer的时候就指定好。他们甚至还主动设置对应的layer.id值,我看了一下ArcGIS的官网,其实应该可以通过title来设置id值的,我还没主动尝试过。

这些图层通过tdtLayer创建完成后,便可以通过之前的地图对象m来进行批量添加了。

javascript 复制代码
const layer1 = tdtLayer('vec');
const layer2 = tdtLayer('cva');
const layer3 = tdtLayer('img');
const layer4 = tdtLayer('cia');
const layer5 = tdtLayer('ter');
const layer6 = tdtLayer('cta');
m.layers.addMany([layer3, layer4])
m.layers.addMany([layer1, layer2, layer5, layer6])

使用中的问题

即使"@arcgis/core": "^4.23.1"安装了,但在运行的时候,会卡在编译地方,感觉像是缺少了什么打包工具。在网上找了几篇文章处理这个问题。

https://blog.csdn.net/qq_34443031/article/details/127285197

安装了文章中提到的两个babel库之后,在编译的时候还是会有某个文件出现问题,定位到了某个文件的某一行,它里面用到了可选链?.符号。但是 "@babel/plugin-proposal-nullish-coalescing-operator""@babel/plugin-proposal-optional-chaining"都已经下载了,也配置好了,仿佛跳过了这个文件一般,仔细一看还真是跳过的那种。于是修改了exclude里面的not,多了一个正则判断。

javascript 复制代码
  configureWebpack: {
    // provide the app's title in webpack's name field, so that
    // it can be accessed in index.html to inject the correct title.
    name: name,
    resolve: {
      alias: {
        '@': resolve('src')
      }
    },
    module: {
      rules: [
        {
          test: /\.m?js$/,
          exclude: {
            and: [/node_modules/],
            not: [
              /@arcgis[\\/]core/,
              /@esri/
            ]
          },
          use: {
            loader: 'babel-loader',
            options: {
              plugins: [
                ['@babel/plugin-proposal-nullish-coalescing-operator'],
                ['@babel/plugin-proposal-optional-chaining']
              ]
            }
          }
        }
      ]
    }
  }

这个方法在使用vue-admin-template进行构建的项目上,没有任何问题,地图能显示出来

相关推荐
WeiXiao_Hyy38 分钟前
成为 Top 1% 的工程师
java·开发语言·javascript·经验分享·后端
吃杠碰小鸡1 小时前
高中数学-数列-导数证明
前端·数学·算法
kingwebo'sZone1 小时前
C#使用Aspose.Words把 word转成图片
前端·c#·word
xjt_09011 小时前
基于 Vue 3 构建企业级 Web Components 组件库
前端·javascript·vue.js
我是伪码农2 小时前
Vue 2.3
前端·javascript·vue.js
夜郎king2 小时前
HTML5 SVG 实现日出日落动画与实时天气可视化
前端·html5·svg 日出日落
辰风沐阳2 小时前
JavaScript 的宏任务和微任务
javascript
夏幻灵3 小时前
HTML5里最常用的十大标签
前端·html·html5
冰暮流星3 小时前
javascript之二重循环练习
开发语言·javascript·数据库
Mr Xu_3 小时前
Vue 3 中 watch 的使用详解:监听响应式数据变化的利器
前端·javascript·vue.js