对于初学者来说,引入CesiumJS是最重要的一步,此文章主要说四种引入方式,vue3和vue2的引入方式基本没有什么区别,都可以用这四种方式。
1、vue-cli-plugin-cesium插件引入
2、npm引入vue-cesium
3、CDN引入
4、手动引入
一、vue-cli-plugin-cesium(仅支持vue-cli3.0+)
简单说就是将Cesium通过插件实现零配置,因为每次配置太麻烦,需要用copy-webpack-plugin插件配置webpack,也就是vue-cli版本小于3.0,配置如下:
... 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"] }) ] ...
复制
CESIUM_BASE_URL是Cesium中内置的全局变量
// cesium-1.96 Source/Core/buildModuleUrl.js ... const cesiumScriptRegex = /((?:.*\/)|^)Cesium\.js(?:\?|\#|$)/; function getBaseUrlFromCesiumScript() { const scripts = document.getElementsByTagName("script"); for (let i = 0, len = scripts.length; i < len; ++i) { const src = scripts[i].getAttribute("src"); const result = cesiumScriptRegex.exec(src); if (result !== null) { return result[1]; } } return undefined; } ... // 不配置的话,默认是 /Cesium/,所以这也是为什么手动引入是创建一个静态文件夹Cesium
复制
详情参见:vue3.x +Cesium vue3.x中安装使用cesium
vue-cli-plugin-cesium安装完之后,需要使用vue invoke初始化
npm install --save-dev vue-cli-plugin-cesium vue invoke vue-cli-plugin-cesium // 可选择是否在main.js中引入Widgets.css // 可选择是否在compontents/下生成示例文件
复制
详情参见:让GIS三维可视化变得简单-Vue项目中集成Cesium
配置完之后就可以在页面中直接使用Cesium对象
<template> <div class="cesiumContainer"> <div id="content-map" class="cesiumContainer-map" ref="targetDom"></div> </div> </template> <script> export default { mounted() { // 实例化Cesium对象 window.viewer = new Cesium.Viewer(node, { // 导航帮助按钮 navigationHelpButton: false, // Geocoder小部件(搜索) geocoder: false, // 时钟尝试延长仿真时间 shouldAnimate: true, // HomeButton小部件 homeButton: true, // SceneModePicker小部件(2/3维切换) sceneModePicker: true, // 创建动画组件 animation: true, // 创建图层组件 baseLayerPicker: false, timeline: true, vrButton: false, infoBox: false, // 相机选中方框 // selectionIndicator: false, fullscreenButton: true, // imageryProvider: imgProvider, // 默认地形,高度为0 // terrainProvider: Cesium.EllipsoidTerrainProvider() }); // cesium 版本 console.log(Cesium.VERSION); }, methods: {}, destroyed() { let gl = viewer.scene.context._originalGLContext; viewer.destroy(); viewer = null; gl.getExtension("WEBGL_lose_context").loseContext(); gl = null; }, }; </script> <style lang="scss" scoped> .cesiumContainer { position: relative; width: 100%; height: 100%; z-index: 0; background: #000; &-map { width: 100%; height: 100%; } } </style>
复制
这里面有一个问题,是初始化时会发送endPoint请求,因为Cesium默认是请求Cesium Ion的资源,这是国外网站,请求比较慢,长时间连接不上就会处于pendding状态。一般是两种方式处理;1、将地形服务给一个默认的底图
// 第一种,给定一张全球图片,替换默认底图 let layer = { url: require("@/assets/img/world.jpg"), name: "地图", rectangle: [-180, -90, 180, 90], }; let imgProvider = new Cesium.SingleTileImageryProvider({ url: layer.url, credit: layer.name, rectangle: Cesium.Rectangle.fromDegrees( layer.rectangle[0], layer.rectangle[1], layer.rectangle[2], layer.rectangle[3] ), }); // 第二种,设置一个纯色canvas let imgProvider = new Cesium.SingleTileImageryProvider({ url: createColorCanvas("#FFF"), rectangle: Cesium.Rectangle.fromDegrees(-180.0, -90.0, 180.0, 90.0) }) window.viewer = new Cesium.Viewer({ ... baseLayerPicker: false,//隐藏默认底图选择控件 imageryProvider: imgProvider, ... }); // cesium 版本 console.log(Cesium.VERSION); function createColorCanvas(color) { var width = 1, height = 1; var canvas = document.createElement('canvas'); canvas.width = width; canvas.height = height; var ctx = canvas.getContext('2d'); ctx.fillStyle = color; ctx.fillRect(0, 0, width, height); return canvas.toDataURL(); }
复制
2、cesium ion官网申请token配置defaultAccessToken
// 尽量使用自己申请的token,别人的token容易改变,会导致一些错误 Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI1Mzk1NjEyMS03YzU2LTRiODgtOGU5NC05NmFhZmY4MjEzYWUiLCJpZCI6NzY0NDMsImlhdCI6MTYzOTQ1OTg5Nn0.2MTeUJoeMx_j3Auv9agF_sT4k73RAJWz9xt2VmFikdw'; window.viewer = new Cesium.Viewer({ ... baseLayerPicker: false,//隐藏默认底图选择控件 imageryProvider: new Cesium.ArcGisMapServerImageryProvider({ name: "img_arcgis", url: "https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer" }), ... }); // 这个请求的是一个在线底图
复制
详情参加: Cesium避免endPoint请求
二、npm引入vue-cesium
1、安装vue-cesium
npm i vue-cesium@2.3.4
复制
全局配置:main.js中配置
import lang from 'vue-cesium/lang/zh-hans' import VueCesium from 'vue-cesium' Vue.use(VueCesium, { // cesiumPath 是指引用的Cesium.js路径,如 // 项目本地的Cesium Build包,vue项目需要将Cesium Build包放static目录: // cesiumPath: /static/Cesium/Cesium.js // 个人在线Cesium Build包: // cesiumPath: 'https://zouyaoji.top/vue-cesium/statics/Cesium/Cesium.js' // 个人在线SuperMap Cesium Build包(在官方基础上二次开发出来的): // cesiumPath: 'https://zouyaoji.top/vue-cesium/statics/SuperMapCesium/Cesium.js' // 官方在线Cesium Build包,有CDN加速,推荐用这个: cesiumPath: 'https://unpkg.com/cesium@1.100/Build/Cesium/Cesium.js', // 指定Cesium.Ion.defaultAccessToken,使用Cesium ion的数据源需要到https://cesium.com/ion/申请一个账户,获取Access Token。不指定的话可能导致 Cesium 在线影像加载不了 accessToken: 'Your Cesium Ion defaultAccessToken', baseLayerPicker: false, lang })
复制
如果不配置cesiumPath的话,也可以将Cesium源码包拷贝到static/public中,在index.html中通过script引入,适配离线开发
用法如下:
<template> <vc-viewer class="viewer" :animation="animation" :timeline="timeline" :camera.sync="camera" @ready="ready"> <vc-layer-imagery> <vc-provider-imagery-openstreetmap></vc-provider-imagery-openstreetmap> </vc-layer-imagery> </vc-viewer> </template> <script> export default { data() { return { animation: true, timeline: true, camera: { position: { lng: 104.06, lat: 30.67, height: 100000 }, heading: 360, pitch: -90, roll: 0 } } }, methods: { ready(cesiumInstance) { const { Cesium, viewer } = cesiumInstance viewer.entities.add({ id: '成都欢迎你', position: Cesium.Cartesian3.fromDegrees(104.06, 30.67, 100), billboard: new Cesium.BillboardGraphics({ image: 'https://www.qianduange.cn/upload/article/favicon.png', scale: 0.1 }), label: new Cesium.LabelGraphics({ text: 'Hello Word', fillColor: Cesium.Color.GOLD, font: '24px sans-serif', horizontalOrigin: 1, outlineColor: new Cesium.Color(0, 0, 0, 1), outlineWidth: 2, pixelOffset: new Cesium.Cartesian2(17, -5), style: Cesium.LabelStyle.FILL }) }) } } } </script> <style> .viewer { width: 100%; height: 400px; } </style>
复制
vue-cesium对vue2.x和3.x有区别,更多的配置和用法可以参见API:Vue Cesium
三、CDN引入
在html中头部引入
<script src="https://cesium.com/downloads/cesiumjs/releases/1.83/Build/Cesium/Cesium.js"></script> <link rel="stylesheet" href="https://cesium.com/downloads/cesiumjs/releases/1.83/Build/Cesium/Widgets/widgets.css">
复制
创建应用
import * as Cesium from 'Cesium' window.viewer = new Cesium.Viewer('dom', { ... })
复制
参见详情 :【一文带你cesium入门】
四、手动引入(离线开发)
1、在static/public下创建Cesium文件夹,原因在上面已经说过了,也可以自由创建,然后对应配置CESIUM_BASE_URL,将node_modules中的cesium/Build/CesiumUnminifed/未压缩的文件夹全部拷贝到新建文件夹下,即Assets、Widgets、Workers、ThirdParty
补充一点,如何更改天空盒
// Cesium/Assets/Textures/SkyBox ,这是打包之后本来就有的文件夹,所以下面的/startmap_2020_16k是再这下面创建文件夹 let groundSkybox = new Cesium.SkyBox({ sources: { positiveX: "/starmap_2020_16k/starmap_2020_16k_px.jpg", negativeX: "/starmap_2020_16k/starmap_2020_16k_mx.jpg", positiveY: "/starmap_2020_16k/starmap_2020_16k_py.jpg", negativeY: "/starmap_2020_16k/starmap_2020_16k_my.jpg", positiveZ: "/starmap_2020_16k/starmap_2020_16k_pz.jpg", negativeZ: "/starmap_2020_16k/starmap_2020_16k_mz.jpg", }, }); viewer.scene.skyBox = groundSkybox;
复制
2、在index.html中引入
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> <meta name="renderer" content="webkit"> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"> <link rel="icon" href="/favicon.ico"> <script type="text/javascript" src="/config/settings.js"></script> <title></title> </head> <body> <div id="app"> </div> <script type="module" src="/src/main.js"></script> <script src="/Cesium/Cesium.js"></script> </body> </html>
复制
css直接从Cesium中引入import 'Cesium/Source/Widgets/widgets.css';可能会报错,参见详情:解决cesium widgets.css is not exported from package
所以一般是将Cesium/Widgets/widgets.css拷贝一份出来,再在main.js中引入
// main.js import '@/assets/styles/cesium-widgets.css'
复制
一些cesium的样式更改就在这个文件里改就行了
其实这会可以不用再安装Cesium了,也就是node_modules中不需要cesium源码包了,程序也是可以正常运行的
五、总结
这篇文章并没有从优化、打包、最优引入方面来分析,仅仅是列出了几种引入方式,主要是在平常开发中,这些也确实够了,最近又看了一位博主的文章,已经说的很明白了,从Cesium前置知识、到打包优化、再到选择最优引入,这一篇文章已经够用了。
参见详情:教程 - 在 Vue3+Ts 中引入 CesiumJS 的最佳实践@2023