• ArcGIS在VUE框架中的构建思想


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

    代码框架

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

    使用到的第三方库 

    1. "dependencies": {
    2. "@arcgis/core": "^4.23.1",
    3. "axios": "0.18.1",
    4. "core-js": "3.6.5",
    5. "echarts": "^4.5.0",
    6. "echarts-gl": "1.0.0-beta.6",
    7. "echarts-liquidfill": "^2.0.6",
    8. "element-ui": "2.15.7",
    9. "events": "^3.3.0",
    10. "js-cookie": "2.2.0",
    11. "lodash": "^4.17.21",
    12. "moment": "^2.29.1",
    13. "normalize.css": "7.0.0",
    14. "nprogress": "0.2.0",
    15. "path-to-regexp": "2.4.0",
    16. "qrcodejs2": "^0.0.2",
    17. "screenfull": "^4.2.1",
    18. "vue": "2.6.10",
    19. "vue-i18n": "^8.18.2",
    20. "vue-router": "3.0.6",
    21. "vuex": "3.1.0"
    22. },
    23. "devDependencies": {
    24. "@vue/cli-plugin-babel": "4.4.4",
    25. "@vue/cli-plugin-eslint": "4.4.4",
    26. "@vue/cli-service": "4.4.4",
    27. "autoprefixer": "9.5.1",
    28. "babel-eslint": "10.1.0",
    29. "babel-plugin-dynamic-import-node": "2.3.3",
    30. "chalk": "2.4.2",
    31. "connect": "3.6.6",
    32. "eslint": "6.7.2",
    33. "eslint-plugin-vue": "6.2.2",
    34. "html-webpack-plugin": "3.2.0",
    35. "mockjs": "1.0.1-beta3",
    36. "runjs": "4.3.2",
    37. "sass": "1.26.8",
    38. "sass-loader": "8.0.2",
    39. "script-ext-html-webpack-plugin": "2.1.3",
    40. "serve-static": "1.13.2",
    41. "svg-sprite-loader": "4.1.3",
    42. "svgo": "1.2.2",
    43. "vue-template-compiler": "2.6.10"
    44. }

    地图封装

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

    DOM 

    Style

    1. #map {
    2. height: calc(100vh);
    3. }

     事件注册

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

    Vue.prototype.$mapEventBus = new Vue()

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

    1. export default {
    2. cleanOverlay: 'cleanOverlay',
    3. hideDike: 'hideDike',
    4. showDikes: 'showDikes',
    5. showBillboard: 'showBillboard',
    6. /** 改变图层可见性 */
    7. changeLayerVisible: 'changeLayerVisible'
    8. }

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

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

    import mapEvent from '@/utils/mapEvent'

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

    1. this.$mapEventBus.$on(mapEvent.cleanOverlay, (data) => {
    2. // 执行某些方法
    3. })
    4. this.$mapEventBus.$on(mapEvent.hideDike, (data) => {
    5. // 执行某些方法
    6. })
    7. this.$mapEventBus.$on(mapEvent.showDikes, (data) => {
    8. // 执行某些方法
    9. })
    10. this.$mapEventBus.$on(mapEvent.showBillboard, (data) => {
    11. // 执行某些方法
    12. })

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

    this.$mapEventBus.$emit(mapEvent.hideDike)
    this.$mapEventBus.$emit(mapEvent.showBillboard, ['layer', 78, 'rain'])

    场景View

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

    1. import Map from '@arcgis/core/Map'
    2. import SceneView from "@arcgis/core/views/SceneView";
    3. import MapView from "@arcgis/core/views/MapView";
    4. const m = new Map({
    5. ground: "world-elevation",
    6. basemap: "topo-vector"
    7. })
    8. // 3D场景的话,使用SceneView
    9. scene= new SceneView({
    10. container: 'map',
    11. map: m,
    12. zoom: 9,
    13. center: [中心坐标值, 中心坐标值],
    14. })
    15. // 普通地图场景的话使用MapView
    16. view= new MapView({
    17. container: 'map',
    18. map: m,
    19. zoom: 10,
    20. center: [中心坐标值, 中心坐标值],
    21. })

    图层加载

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

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

    1. export default {
    2. tileInfo: {
    3. rows: 256,
    4. cols: 256,
    5. origin: {
    6. x: -20037508.342787,
    7. y: 20037508.342787,
    8. },
    9. compressionQuality: 0,
    10. spatialReference: {
    11. wkid: 102113
    12. },
    13. lods: [
    14. {
    15. endTileCol: 31,
    16. endTileRow: 31,
    17. level: 5,
    18. resolution: 4891.96981024998,
    19. scale: 18489297.737236,
    20. startTileCol: 0,
    21. startTileRow: 0,
    22. },
    23. {
    24. endTileCol: 63,
    25. endTileRow: 63,
    26. level: 6,
    27. resolution: 2445.98490512499,
    28. scale: 9244648.868618,
    29. startTileCol: 0,
    30. startTileRow: 0,
    31. },
    32. {
    33. endTileCol: 127,
    34. endTileRow: 127,
    35. level: 7,
    36. resolution: 1222.992452562495,
    37. scale: 4622324.434309,
    38. startTileCol: 0,
    39. startTileRow: 0,
    40. },
    41. {
    42. endTileCol: 255,
    43. endTileRow: 255,
    44. level: 8,
    45. resolution: 611.4962262812475,
    46. scale: 2311162.2171545,
    47. startTileCol: 0,
    48. startTileRow: 0,
    49. },
    50. {
    51. endTileCol: 511,
    52. endTileRow: 511,
    53. level: 9,
    54. resolution: 305.74811314062373,
    55. scale: 1155581.10857725,
    56. startTileCol: 0,
    57. startTileRow: 0,
    58. },
    59. {
    60. endTileCol: 1023,
    61. endTileRow: 1023,
    62. level: 10,
    63. resolution: 152.87405657031186,
    64. scale: 577790.554288625,
    65. startTileCol: 0,
    66. startTileRow: 0,
    67. },
    68. {
    69. endTileCol: 2047,
    70. endTileRow: 2047,
    71. level: 11,
    72. resolution: 76.43702828515593,
    73. scale: 288895.2771443125,
    74. startTileCol: 0,
    75. startTileRow: 0,
    76. },
    77. {
    78. endTileCol: 4095,
    79. endTileRow: 4095,
    80. level: 12,
    81. resolution: 38.218514142577966,
    82. scale: 144447.63857215625,
    83. startTileCol: 0,
    84. startTileRow: 0,
    85. },
    86. {
    87. endTileCol: 8191,
    88. endTileRow: 8191,
    89. level: 13,
    90. resolution: 19.109257071288983,
    91. scale: 72223.81928607813,
    92. startTileCol: 0,
    93. startTileRow: 0,
    94. },
    95. {
    96. endTileCol: 16383,
    97. endTileRow: 16383,
    98. level: 14,
    99. resolution: 9.554628535644492,
    100. scale: 36111.909643039064,
    101. startTileCol: 0,
    102. startTileRow: 0,
    103. },
    104. {
    105. endTileCol: 32767,
    106. endTileRow: 32767,
    107. level: 15,
    108. resolution: 4.777314267822246,
    109. scale: 18055.954821519532,
    110. startTileCol: 0,
    111. startTileRow: 0,
    112. },
    113. {
    114. endTileCol: 65534,
    115. endTileRow: 65534,
    116. level: 16,
    117. resolution: 2.388657133911123,
    118. scale: 9027.977410759766,
    119. startTileCol: 0,
    120. startTileRow: 0,
    121. },
    122. {
    123. endTileCol: 131069,
    124. endTileRow: 131069,
    125. level: 17,
    126. resolution: 1.1943285669555614,
    127. scale: 4513.988705379883,
    128. startTileCol: 0,
    129. startTileRow: 0,
    130. },
    131. {
    132. endTileCol: 262138,
    133. endTileRow: 262138,
    134. level: 18,
    135. resolution: 0.5971642834777807,
    136. scale: 2256.9943526899415,
    137. startTileCol: 0,
    138. startTileRow: 0,
    139. }
    140. ]
    141. },
    142. }

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

    1. import WebTileLayer from "@arcgis/core/layers/WebTileLayer";
    2. import SpatialReference from "@arcgis/core/geometry/SpatialReference";
    3. import Extent from "@arcgis/core/geometry/Extent";
    4. import tileInfo from './tdtconfig';
    5. function tdtLayer(type,visible){
    6. 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}`;
    7. const tiledLayer = new WebTileLayer({
    8. urlTemplate: url,
    9. subDomains: ["t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7"],
    10. spatialReference: new SpatialReference({
    11. wkid: 102113,
    12. }),
    13. fullExtent: new Extent({
    14. xmax: 20038088.3427892,
    15. xmin: -20038088.3427892,
    16. ymax: 20038088.3427892,
    17. ymin: -20038088.3427892,
    18. spatialReference: {wkid: 102113}
    19. }),
    20. initialExtent: new Extent({
    21. xmax: 13211664.142019678,
    22. xmin: 13077211.409266088,
    23. ymax: 2843822.418908416,
    24. ymin: 2810801.622689228,
    25. spatialReference: {wkid: 102113}
    26. }),
    27. tileInfo: tileInfo.tileInfo,
    28. visible
    29. });
    30. return tiledLayer;
    31. }
    32. export {
    33. tdtLayer,
    34. }

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

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

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

    1. const layer1 = tdtLayer('vec');
    2. const layer2 = tdtLayer('cva');
    3. const layer3 = tdtLayer('img');
    4. const layer4 = tdtLayer('cia');
    5. const layer5 = tdtLayer('ter');
    6. const layer6 = tdtLayer('cta');
    7. m.layers.addMany([layer3, layer4])
    8. 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,多了一个正则判断。

    1. configureWebpack: {
    2. // provide the app's title in webpack's name field, so that
    3. // it can be accessed in index.html to inject the correct title.
    4. name: name,
    5. resolve: {
    6. alias: {
    7. '@': resolve('src')
    8. }
    9. },
    10. module: {
    11. rules: [
    12. {
    13. test: /\.m?js$/,
    14. exclude: {
    15. and: [/node_modules/],
    16. not: [
    17. /@arcgis[\\/]core/,
    18. /@esri/
    19. ]
    20. },
    21. use: {
    22. loader: 'babel-loader',
    23. options: {
    24. plugins: [
    25. ['@babel/plugin-proposal-nullish-coalescing-operator'],
    26. ['@babel/plugin-proposal-optional-chaining']
    27. ]
    28. }
    29. }
    30. }
    31. ]
    32. }
    33. }

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

  • 相关阅读:
    SpringBoot启动失败报错,spring.profiles.active:@env@中环境变量@无法识别报错_active: @env@
    PCL点云处理之基于FPFH特征的全局配准流程具体实现(二百二十一)
    【深度学习】UniControl 一个统一的扩散模型用于可控的野外视觉生成
    秋招面经第七弹:网易一面-数据开发工程师
    【性能测试】初识 Jmeter 中的 BeanShell
    JAVA计算机毕业设计兴澜幼儿园管理系统Mybatis+源码+数据库+lw文档+系统+调试部署
    Java下Properties类的使用(写出和读入)
    外包干了4年,技术退步明显.......
    Django-Multitenant,分布式多租户数据库项目实战(Python/Django+Postgres+Citus)
    喝汽水问题
  • 原文地址:https://blog.csdn.net/GhostPaints/article/details/133807132