Vue3.x 项目中如何使用Cesium构建三维地图项目
本文列举两种常用使用方法:
1、使用vue-cli-plugin-cesium 插件安装cesium(配置较为简单)
2、安装cesium 手动配置webpack
一、使用vue-cli-plugin-cesium 插件安装cesium
使用vuecli创建vue3.x的项目,因为插件基于webpack的,当前插件只支持 VueCLI3.0+ 版本哦
1. 创建项目
vue create vue3-cesium
2. 安装 vue-cli-plugin-cesium
vue add vue-cli-plugin-cesium
// 非全局安装的vue-cli可以
npx vue add vue-cli-plugin-cesium
或npm安装
// npm
npm install --save-dev vue-cli-plugin-cesium
// yarn
yarn add vue-cli-plugin-cesium
安装完成后我们要使用 vue invoke 来初始化这个插件
vue invoke vue-cli-plugin-cesium
// 非全局安装的vue-cli可以
npx vue invoke vue-cli-plugin-cesium
安装过程会有询问:
在?vue invoke ?或?vue add ?的过程中会有三个询问
询问一
Please?choose?a?version?of?'cesium'?from?this?list
请在列表中选择?cesium?的版本
在此选择想使用的?Cesium ?版本
询问二
Whether?to?import?styles?globally.?
This?operation?will?automatically?import?widgets.css?in?main.js
是否全局引入样式,该操作将自动在main.js引入widgets.css?
此项默认为 yes,该操作将自动在 main.js 引入 widgets.css,即全局引入 Cesium 的 css 样式
如果此项设置为 no,那么开发时我们要手动引入widgets.css 样式文件,引入命令如下
import?"cesium/Widgets/widgets.css"
询问三
Whether?to?add?sample?components?to?the?project?components?directory
是否添加示例组件到项目components目录?
此选项默认为 yes,该操作会自动在?src/components ?文件夹下生成?CesiumExample ?文件夹,此文件夹中包含一些 Cesium 的使用示例供参考
如果此项设置为 no,则不生成示例文件
?如果安装完成启动项目时报错?
Error:Cesium is no-undef
请检查配置一下eslint??"no-undef": 0,
module.exports = {
root: true,
env: {
node: true
},
'extends': [
'plugin:vue/vue3-essential',
'eslint:recommended'
],
parserOptions: {
parser: 'babel-eslint'
},
rules: {
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
"no-undef": 0,
'prefer-const': 'off',
"no-irregular-whitespace": "off", //这禁止掉 空格报错检查
'no-unused-vars': 'off', //禁止定义变量未使用报错
"no-empty": 0
}
}
安装完成后的main.js
import {
createApp
} from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import 'cesium/Widgets/widgets.css'
Cesium.Ion.defaultAccessToken = '在cesium官网申请的token'
createApp(App).use(store).use(router).mount('#app')
Cesium.Ion.defaultAccessToken 用户配置我们自己的cesium token的,下面详细说
在vue组件中使用:
<template>
<div class="map-box">
<div id="cesiumContainer"></div>
</div>
</template>
<script>
import { onMounted } from "vue";
export default {
name: "",
mounted() {
// var viewer = new Cesium.CesiumWidget('cesiumContainer')
// var viewer = new Cesium.Viewer("cesiumContainer", {
// animation: false, //是否显示动画控件
// homeButton: true, //是否显示home键
// geocoder: false, //是否显示地名查找控件 如果设置为true,则无法查询
// baseLayerPicker: false, //是否显示图层选择控件
// timeline: false, //是否显示时间线控件
// fullscreenButton: true, //是否全屏显示
// scene3DOnly: false, //如果设置为true,则所有几何图形以3D模式绘制以节约GPU资源
// infoBox: false, //是否显示点击要素之后显示的信息
// sceneModePicker: false, //是否显示投影方式控件 三维/二维
// navigationInstructionsInitiallyVisible: true,
// navigationHelpButton: false, //是否显示帮助信息控件
// selectionIndicator: false, //是否显示指示器组件
// // 地形
// terrainProvider:new Cesium.createWorldTerrain({
// requestVertexNormals:true,
// requestWaterMask:true
// }),
// //1 加载天地图
// imageryProvider: new Cesium.WebMapTileServiceImageryProvider({
// url:
// "http://t0.tianditu.com/img_w/wmts?service=wmts&request=GetTile&version=1.0.0&LAYER=img&tileMatrixSet=w&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}&style=default&format=tiles&tk=你的天地图申请的key",
// layer: "tdtBasicLayer",
// style: "default",
// format: "image/jpeg",
// tileMatrixSetID: "GoogleMapsCompatible",
// show: false,
// mininumLevel: 0,
// maximumLevel: 16
// })
// });
// console.log(viewer)
},
setup() {
onMounted(() => {
Cesium.Camera.DEFAULT_VIEW_RECTANGLE = Cesium.Rectangle.fromDegrees(80, 22, 130, 55)// 默认定位到中国上空,home定位到中国范围
var viewer = new Cesium.Viewer("cesiumContainer", {
animation: false, //是否显示动画控件
homeButton: true, //是否显示home键
geocoder: false, //是否显示地名查找控件 如果设置为true,则无法查询
baseLayerPicker: false, //是否显示图层选择控件
timeline: false, //是否显示时间线控件
fullscreenButton: true, //是否全屏显示
scene3DOnly: false, //如果设置为true,则所有几何图形以3D模式绘制以节约GPU资源
infoBox: false, //是否显示点击要素之后显示的信息
sceneModePicker: true, //是否显示投影方式控件 三维/二维
navigationInstructionsInitiallyVisible: true,
navigationHelpButton: false, //是否显示帮助信息控件
selectionIndicator: false, //是否显示指示器组件
// 地形
terrainProvider: new Cesium.createWorldTerrain({
requestVertexNormals: true,
requestWaterMask: true
}),
//1 加载天地图
imageryProvider: new Cesium.WebMapTileServiceImageryProvider({
url:
"http://t0.tianditu.com/img_w/wmts?service=wmts&request=GetTile&version=1.0.0&LAYER=img&tileMatrixSet=w&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}&style=default&format=tiles&tk=你的天地图申请的key",
layer: "tdtBasicLayer",
style: "default",
format: "image/jpeg",
tileMatrixSetID: "GoogleMapsCompatible",
show: false,
mininumLevel: 0,
maximumLevel: 16
})
});
//调用影响中文注记服务
viewer.imageryLayers.addImageryProvider(new Cesium.WebMapTileServiceImageryProvider({
url: "http://{s}.tianditu.gov.cn/cia_c/wmts?service=wmts&request=GetTile&version=1.0.0" +
"&LAYER=cia&tileMatrixSet=c&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}" +
"&style=default&format=tiles&tk=你的天地图申请的key",
layer: "tdtImg_c",
style: "default",
format: "tiles",
tileMatrixSetID: "c",
subdomains: ["t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7"],
tilingScheme: new Cesium.GeographicTilingScheme(),
tileMatrixLabels: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19"],
maximumLevel: 50,
show: false
}));
// 隐藏版权
viewer._cesiumWidget._creditContainer.style.display = "none";
// 修改home按钮功能
viewer.homeButton.viewModel.command.beforeExecute.addEventListener((e) => {
console.log("click", e)
e.cancel = true
// // 方案一:你要飞的位置,根据点来设定
// viewer.camera.flyTo({
// destination: Cartesian3.fromDegrees(117.16, 32.71, 15000.0)
// })
// 返回初始设置位置
// viewer.camera.flyHome(1)
// 方案二:你要飞的位置,根据相机的视角来确定
viewer.camera.flyTo({
destination: Cesium.Rectangle.fromDegrees(80, 22, 130, 55)// home定位到中国范围
})
setTimeout(() => {
let currentViewRect = viewer.camera.computeViewRectangle(),
params = []
params[2] = Cesium.Math.toDegrees(currentViewRect.east);
params[3] = Cesium.Math.toDegrees(currentViewRect.north);
params[0] = Cesium.Math.toDegrees(currentViewRect.west);
params[1] = Cesium.Math.toDegrees(currentViewRect.south);
console.log("当前视角", params)
}, 3000)
})
console.log("view", viewer)
})
}
};
</script>
<style scoped>
.map-box {
width: 100%;
height: 100%;
}
#cesiumContainer {
width: 100%;
height: 100%;
}
</style>
运行效果:
上面我们可以看到运行时候回报出 我们当前使用的是默认的token,需要我们去cesium官网申请一个token,以便后期官方更新内容我们可以使用等,在main.js中设置一下
Cesium.Ion.defaultAccessToken = "你申请的token"? 配置后就不会有提示了。
当项目运行出地球说明配置成功了,就可以进行开发了。
资料:vue-cli-plugin-cesium
?
?二、安装cesium 手动配置webpack
1、创建vue-cli项目?
2、在创建完成的项目中安装cesium
npm i cesium --save
3、安装插件?copy-webpack-plugin 版本5.0.1
npm i copy-webpack-plugin@5.0.1 -D
4、创建vue.config.js文件,配置webpack
const CopyWebpackPlugin = require("copy-webpack-plugin");
const webpack = require("webpack");
const path = require("path");
let cesiumSource = "./node_modules/cesium/Source";
let cesiumWorkers = "Workers";
module.exports = {
configureWebpack: {
resolve: {
alias: {
"@": path.resolve("src"),
},
},
amd: {
// Cesium源码模块化使用的requireJs
// 此配置允许webpack友好地在铯中使用require,使webpack打包cesium
// 告诉Cesium, AMD的webpack版本用来评估要求的声明是不符合标准的toUrl功能
toUrlUndefined: true
},
module: {
// 解决require引入警告
unknownContextCritical: false
},
plugins: [
new CopyWebpackPlugin([{
from: path.join(cesiumSource, cesiumWorkers),
to: "Workers"
}, ]),
new CopyWebpackPlugin([{
from: path.join(cesiumSource, "Assets"),
to: "Assets"
}, ]),
new CopyWebpackPlugin([{
from: path.join(cesiumSource, "Widgets"),
to: "Widgets"
}, ]),
new CopyWebpackPlugin([{
from: path.join(cesiumSource, "ThirdParty/Workers"),
to: "ThirdParty/Workers",
}, ]),
new webpack.DefinePlugin({
CESIUM_BASE_URL: JSON.stringify("./"),
}),
// 使Cesium对象实例可在每个js中使用而无须import
new webpack.ProvidePlugin({
Cesium: ["cesium/Source/Cesium"]
})
],
module: {
unknownContextCritical: false,
unknownContextRegExp: /\/cesium\/cesium\/Source\/Core\/buildModuleUrl\.js/,
},
},
};
注意:
(1)配置ProvidePlugin? ?
通过new webpack.ProvidePlugin? 自动加载模块,而不必到处 import 或 require?
// 使Cesium对象实例可在每个js中使用而无须import
new webpack.ProvidePlugin({
Cesium: ["cesium/Source/Cesium"]
})
?使用:无需导出引入,直接使用
<script>
import { onMounted } from "@vue/runtime-core";
export default{
setup() {
onMounted(() => {
let viewer = new Cesium.Viewer("cesiumContainer");
});
return {};
},
};
</script>
(2)不配置ProvidePlugin?
如果不配置ProvidePlugin,使用cesium变量需要手动配置引入:如下
main.js 引入,使用provide/inject 或?config.globalProperties (自行百度如何使用)
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
// import 'cesium/Source/Widgets/widgets.css';
// const Cesium = require("cesium/Source/Cesium");
import * as Cesium from 'cesium/Source/Cesium';
import 'cesium/Source/Widgets/widgets.css'
const Vue = createApp(App)
Vue.provide('Cesium',Cesium)
Vue.use(store).use(router).mount('#app')
使用:
<template>
<div id="cesiumContainer"></div>
</template>
使用一:setup() 中使用
<script>
import { defineComponent, inject, onMounted } from "@vue/runtime-core";
export default{
setup() {
let Cesium = inject("Cesium");
onMounted(() => {
let viewer = new Cesium.Viewer("cesiumContainer");
});
return {};
},
};
</script>
使用二:选项式使用
<script>
export default {
inject: ['Cesium'],
mounted() {
const Cesium = this.Cesium
let viewer = new Cesium.Viewer("cesiumContainer");
},
methods: {
loadMap() {
let viewer = new this.Cesium.Viewer("aboutCesium");
}
}
}
</script>
运行项目就可以看到效果:
?
|