npm install vue-cli -g
vue create 'dome'.......
这就略过了
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":
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}
]
})
在文件中想要使用必须加上前缀,将它抽离是怕到时候文件比较混乱,管理起来更直观方便。
...mapState({
esri: state => state.map.esri,
})
// 这里我就一同记录了吧
// 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
};
<template>
<div id="app">
<router-view/>
</div>
</template>
<script>
export default {
name: 'App'
}
</script>
<style>
#app {
width: 100vw;
height: 100vh;
}
</style>
<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>
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>
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
})
}