vue + arcgis for javascript 实战(一)配置页面并显示页面

最近接触Arcgis。 感觉很奇葩,自己做出来的东西都没有那种归属感,有种摸不透的感觉,很多的东西api封装好了,但是看着就是不习惯,甚至是存在漏洞。我不怎么喜欢看这类的官方的api文档,arcgis官方的例子也不是那么的全,都是散开的。另外现在arcgis 版本更新,3版本和4版本,导致想在网上搜索资料都应为在版本不同而却步。
我的dome是vue版本。
npm install vue-cli -g
vue create 'dome'.......
这就略过了
main 文件是干净的。用到了vuex,router。公共css 也就是内外边距为 0 什么的
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
// CSS
import 'element-ui/lib/theme-chalk/index.css';
import '@arcgis/core/assets/esri/themes/dark/main.css';
import '@/assets/css/global.css';
import '@/assets/font/iconfont.css'
// js
Vue.config.productionTip = false
import ElementUI from 'element-ui';

new Vue({
  router,
  store,
  render: h => h(App),
}).$mount('#app')

这是package.json。可以看到是用到的esri-load;
之前用到了"@arcgis/core": “^4.18.0”;好用,但是bug很多。不适用。

"dependencies": {
    "axios": "^0.21.1",
    "core-js": "^3.6.5",
    "element-ui": "^2.13.2",
    "esri-loader": "^2.16.0",
    "qs": "^6.9.4",
    "stylus": "^0.54.7",
    "stylus-loader": "^3.0.2",
    "vue": "^2.6.11",
    "vue-router": "^3.0.1",
    "vuex": "^3.6.0",
    "vuex-persistedstate": "^4.0.0-beta.1"
  },
  "devDependencies":
router 文件,二级路由
import Vue from 'vue'
import Router from 'vue-router'
import home from '@/views/home'
import Map from '@/components/main/Map/index'
Vue.use(Router)

export default new Router({
  routes: [
    {path: '/', redirect: '/home'},
    {path: '/home', name: 'home', component: home, redirect: '/home/map', children: [
        {path: '/home/map', name: 'Map', component: Map}
  ]
})
store 页面 这里的store 是配置过模块化的
在文件中想要使用必须加上前缀,将它抽离是怕到时候文件比较混乱,管理起来更直观方便。
    ...mapState({
      esri: state => state.map.esri,
    })

vue + arcgis for javascript 实战(一)配置页面并显示页面_第1张图片

// 这里我就一同记录了吧

// index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)

const modulesFiles = require.context('./modules', true, /\.js$/)
const modules = modulesFiles.keys().reduce((modules, modulePath) => { 
    const moduleName = modulePath.replace(/^\.\/(.*)\.\w+$/, '$1') // modulesFiles.keys()获取所有js文件的相对路径
    const value = modulesFiles(modulePath) // 对文件路径进行处理,获取文件名 比如 './app.js' => 'app'
    modules[moduleName] = value.default // 获取一个js文件(state)下的所有信息,这一步相当于 -- import 路径
    return modules// 整合到一个对象modules中
}, {})// 开始下一个迭代,直到所有文件被浏览

const store = new Vuex.Store({
    modules
})

export default store
// ##################################== 分割线 ==###############################################
// modules/map.js
const state = {
  esri: {},
  map: null,
}

const mutations = {
  setEsri: (state, commit) => state.esri = commit,
  setMap: (state, commit) => state.map = commit,
}
const getters = {
  getEsri: (state) => state.esri
}
const actions = {

}

export default {
  state,
  mutations,
  getters,
  actions
};
app页面
<template>
  <div id="app">
    <router-view/>
  </div>
</template>

<script>
export default {
  name: 'App'
}
</script>

<style>
#app {
  width: 100vw;
  height: 100vh;
}
</style>
从路由配置上来看出有个views的文件夹,路径path: views/home
配置了一个简单的管理系统的页面。这步就不记录了。
<template>
  <el-container>
    <el-header></el-header>

    <el-container>
      <el-aside  :width="isCollapse ? '64px' : '200px'">
        <div class="toggle-button" @click="isCollapse = !isCollapse">|||</div>
        <menus :Collapse="isCollapse"></menus>
      </el-aside>

      <el-main><router-view/></el-main>

    </el-container>

  </el-container>
</template>

<script>
  import menus from '@/components/aside/menu'
  export default {
    components: {
      menus
    },
    data() {
      return {
        isCollapse: true,
      }
    },
  }
</script>

<style>
  body>#app>.el-container {
    height: 100%;
  }

  .el-header,
  .el-footer {
    background: #373d41;
    color: #fff;
    text-align: center;
  }

  .el-aside {
    background: #333744;
    color: #fff;
    text-align: center;
    position: relative;
  }
  .toggle-button{
    background: #4a5064;
    text-align: center;
    font-size: 10px;
    line-height: 24px;
    color: #fff;
    letter-spacing: 0.2em;
    cursor: pointer;
  }
  .el-main {
    background: #eaedf1;
    color: #333;
    padding: 0 !important;
    margin: 0;
  }
</style>
computents的文件夹,路径path: computents/Map/index
1. 在这个文件的全局创建map,view。在该文件中是可以直接使用它。
2. option,Modules 这两个属性后面将他们抽离单独成为一个配置文件。
3. init 函数 使用"esri-loader"模块加载导入,使用then回调执行后续代码。
4. 第一个then 回调,使用for in 将它挨个添加以键值对形式存入一个对象中,并存储在vuex中。便于其他位置使用它。
5. 第二个then 回调初始化地图,这里我使用谷歌天地图加入它。但是现在使用esri 实例就不能直接使用了,由于vuex的原因,在这个页面中需要通过this.esri 或者是this.getEsri来指向。
6. 地图的layer我是使用的Basemap来导入提前设置好的天地图。将它放在map中。
7. 计算属性中我是使用的vuex的计算属性来读取esri对象。
8. 可以看出import 导入了一个TintLayer 实例。这个实例是加载天地图的,传入一些属性后便成为一个图层。
<template>
<div class="Container">
  <div id="map"></div>
</div>
</template>

<script>
const option = {
        url: "https://js.arcgis.com/4.15/init.js",
        css: "https://js.arcgis.com/4.18/esri/themes/light/main.css"
      };
const Modules = [
  "esri/Map",
  "esri/Basemap",
  "esri/views/MapView",
  "esri/request",
  "esri/layers/BaseTileLayer",
];
let map, view;
import { loadModules } from "esri-loader";
import { mapState, mapMutations, mapGetters } from 'vuex'
import { TintLayer } from './Baselayer'	// 导入自定义的天地图对象文件。
export default {
  name: "index",
  components: {},
  data() {
    return {

    };
  },

  mounted() {
    this.init();
  },

  methods: {
    init() {
      loadModules(Modules, option).then(this.setModule).then(this.initMap);
    },
    setModule(args) {
      let esri = {};
      for (let k in args) {
	    let name = Modules[k].split("/").pop();
	    esri[name] = args[k];
      }
      this.setEsri(esri);
    },
    initMap() {
      const google_lay = TintLayer({
          url: 'http://mt0.google.cn/vt/lyrs=t,r&hl=zh-CN&gl=cn&x={x}&y={y}&z={z}',
          id: 'google_lay',
          visible: true,
          baselayer: true,
          store: this.getEsri
        });
      const raster_lay = TintLayer({
          url: 'http://mt0.google.cn/vt/lyrs=s@702&hl=zh-CN&gl=cn&x={x}&y={y}&z={z}&s=Ga',
          id: 'raster_lay',
          visible: false,
          baselayer: true,
          store: this.getEsri
        });
      const basemap = new this.esri.Basemap({ baseLayers: [google_lay, raster_lay] });
      map = new this.esri.Map({ basemap });
      view = new this.esri.MapView({
        container: "map",
        map,
        center: [114, 30],
        zoom: 6
      });
    }
  },
  computed: {
    ...mapState({
      esri: state => state.map.esri,
    }),
    ...mapGetters(['getEsri'])
  },

  //  End
}
</script>

<style lang='stylus' scoped>
.Container {
  width: 100%;
  height: 100%;
  #map {
    width: 100%;
    height: 100%;
  }
}
</style>

Baselayer文件
1. 这个实例是在网上搜的,具体的我也不是很清楚。在这个里面我修改了导入的参数。
2. 5个属性:url ,id,visible,baselayer,store
3. 为什么有接收一个store呢,这个是vuex 中存储好的modules。可能有人会想了,我直接引入vuex 还香些。
4. 关于上条,我给你的答案是"esri-loader"模块加载是异步的,当你init函数还没加载出来时,这个js文件都读完了。此时vuex中的对象还是一个空对象。
export const TintLayer = ({url, id = null,visible = true, baselayer = false, store}) => {
  const TintLayer = store.BaseTileLayer.createSubclass({
  properties: {
    urlTemplate: null,
  },

  // 为给定级别、行和列生成平铺url
  getTileUrl: function (level, row, col) {
    return this.urlTemplate.replace("{z}", level).replace("{x}", col).replace("{y}", row);
  },

  //此方法获取指定级别和大小的平铺。
  //重写此方法以处理从服务器返回的数据。
  fetchTile: function (level, row, col) {

    //调用getTileUrl()方法来构造要平铺的URL
    //对于层视图提供的给定标高、行和列
    var url = this.getTileUrl(level, row, col);

    //基于生成的url请求平铺
    //将allowImageDataAccess设置为true以允许
    //跨域访问以创建用于3D的WebGL纹理。
    return store.request(url, {
      responseType: "image",
      allowImageDataAccess: true
    })
      .then(function (response) {
        //esri请求成功解析时
        //从响应中获取图像
        var image = response.data;
        var width = this.tileInfo.size[0];
        var height = this.tileInfo.size[0];

        // 使用2D渲染上下文创建canvas
        var canvas = document.createElement("canvas");
        var context = canvas.getContext("2d");
        canvas.width = width;
        canvas.height = height;

        // 将混合图像绘制到canvas上
        context.drawImage(image, 0, 0, width, height);

        return canvas;
      }.bind(this));
  }
});
  return new TintLayer({
    urlTemplate: url,
    id,
    visible,
    baselayer
  })
}

就先写这里吧,这片文章弄完应该完成了3件事,将arcgis模块存放在了全局的vuex中,初始化地图并显示地图,使用不同的天地图作为底图。

你可能感兴趣的:(arcgis,oplayers,vue,vue,arcgis)