CesiumJS
库与所有构建系统和框架兼容。但是,考虑到渲染引擎的性质,在使用Vite
或webpack
时,您需要采取一些额外的步骤来为您的应用程序配置它。尽管找各种资料完全可以很快照着完成,但各种配置背后的作用和原理 是什么呢?于是本文总结在
Vite
中使用CesiumJs
详细步骤,并通过debug
的方式分析并解决过程中出现的问题。
1. 创建账号获取token
使用Cesium
需要注册Cesium ion账户(免费)获取token
:
2. 下载Cesium资源包
Cesium
提供CDN
和npm
两种方式引入资源包。CDN
方式这里不做赘述,看这里。
使用npm下载cesium依赖:
npm install cesium
3. 引入控件样式文件、设置Ion默认token
widgets.css
文件是cesium
内置控件的样式,包括导航控件(Navigation
)、时间轴控件(Timeline
)、动画控件(Animation
)、全屏按钮(Fullscreen Button
)、地理编码搜索框(Geocoder
)和场景模式切换器(SceneModePicker
)等。
ts
// main.ts
import "cesium/Build/Cesium/Widgets/widgets.css";
import { Ion } from 'cesium';
Ion.defaultAccessToken = 'your token';
3.1 设置Ion Token的作用
访问cesium
的一些地图服务需要用到,如请求一些地形数据 (Terrain
)、影像数据 (Imagery
)、3D Tiles
数据等。但如果不设置自己的token
,在源码 中可以看到Ion
有一个默认的token
:
js
// packages/engine/Source/Core/Ion.js
const defaultAccessToken =
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI0ZDdmNWJiNy0wMmNlLTQ1MWUtODM2YS02NGM1MTBlOGMwMWQiLCJpZCI6MjU5LCJpYXQiOjE3MzMxNTc4OTV9.B3URHf0VdHDtGckb-hv7uqATdn8KfvkiuoAFZUq8tAo";
const Ion = {};
Ion.defaultAccessToken = defaultAccessToken;
默认的token
请求数量有限;注册用户token
会有更多的月度配额;付费的token
可以访问更高分辨率的数据等。
4. 创建一个demo_cesium.vue
文件:
vue
<!-- demo_cesium.vue -->
<template>
<div id="cesiumContainer"></div>
</template>
<script lang="ts" setup>
import { Cartesian3, createOsmBuildingsAsync, Ion, Terrain, Viewer } from 'cesium';
import { onMounted } from 'vue';
// Initialize the Cesium Viewer in the HTML element with the `cesiumContainer` ID.
onMounted(async () => {
const viewer = new Viewer('cesiumContainer', {
terrain: Terrain.fromWorldTerrain(),
});
// Fly the camera to San Francisco at the given longitude, latitude, and height.
viewer.camera.flyTo({
destination: Cartesian3.fromDegrees(-122.4175, 37.655, 400)
});
// Add Cesium OSM Buildings, a global 3D buildings layer.
const buildingTileset = await createOsmBuildingsAsync();
viewer.scene.primitives.add(buildingTileset);
})
</script>
<style lang="less" scoped>
#cesiumContainer {
width: 100%;
height: 100%;
}
</style>
打开浏览器devtool
面板,发现如下报错:
根据报错链接进入source
面板断点发现:
显然JSON.parse
不能解析html
文本,所以报错。在调用堆栈中找到上层函数调用:
发现 Resource.fetchJson
这个地址: "http://192.168.31.212:5173/welcome-to-my-website/node_modules/.vite/deps/Assets/approximateTerrainHeights.json"
那现在出现2
个问题:
- 为什么
fetchJson
这个地址最终会变成JSON.parse
根html
文本? "http://192.168.31.212:5173/welcome-to-my-website/node_modules/.vite/deps"
这个前缀哪里来的?
第1个问题暂且可以搁置不管,解决报错需要寻找第2个问题的答案 。于是鼠标hover
在buildModuleUrl
方法上:
点击[[FunctionLocation]]
查看其实现:
同样的方式我们进入getCesiumBaseUrl
方法:
发现源码中判断CESIUM_BASE_URL
如果为空,就判断当前的模块环境,如果是ESM则是getAbsoluteUri(".", import.meta.url)
其结果就是我们想要验证的前缀:"http://192.168.31.212:5173/welcome-to-my-website/node_modules/.vite/deps/"
。
所以我们要配置CESIUM_BASE_URL
!
4. 托管Cesium静态资源文件、配置 CESIUM_BASE_URL
4.1 配置CESIUM_BASE_URL的目的
CesiumJS
需要vite
服务托管一些静态文件,例如 Web Worker
和 SVG
图标。那这些资源在哪呢?我们第一步安装cesium
时,它们被安装到了node_modules
下:
我们发现上图中箭头指向的Assets/approximateTerrainHeights.json
文件正是上文debug
解析的文件。
4.2 配置 CESIUM_BASE_URL
其实,开发阶段 我们完全可以直接通过 /node_modules/cesium ...
去访问静态资源:
所以理论上我们将window.CESIUM_BASE_URL
设置为/welcome-to-my-website/node_modules/cesium/Build/Cesium
即可成功,验证如下:
ts
// vite.config.ts
export default defineConfig({
base: '/welcome-to-my-website',
define: {
CESIUM_BASE_URL: JSON.stringify(`/welcome-to-my-website/node_modules/cesium/Build/Cesium`),
}
});
确实可以成功:
但既然使用了构建工具就必须考虑生成环境的打包路径。 正常打包vite
会将所有静态资源都打包在assets
下:
因此我们需要在开发环境 和生产环境 可以用同样的路径访问到 Cesium
静态资源,而viteStaticCopy包做了这件事。于是我们进行如下配置:
ts
// vite.config.ts
import vue from "@vitejs/plugin-vue";
import { viteStaticCopy } from "vite-plugin-static-copy";
const base = "/welcome-to-my-website";
const cesiumSource = "node_modules/cesium/Build/Cesium";
const cesiumBaseUrl = "cesiumStatic";
export default defineConfig({
base,
define: {
CESIUM_BASE_URL: JSON.stringify(`${base}/${cesiumBaseUrl}`),
},
plugins: [
vue(),
viteStaticCopy({
targets: [
{ src: `${cesiumSource}/ThirdParty`, dest: cesiumBaseUrl },
{ src: `${cesiumSource}/Workers`, dest: cesiumBaseUrl },
{ src: `${cesiumSource}/Assets`, dest: cesiumBaseUrl },
{ src: `${cesiumSource}/Widgets`, dest: cesiumBaseUrl },
],
}),
]
});
此时通过 http://192.168.31.212:5173/welcome-to-my-website/cesiumStatic/Assets/Images/ion-credit.png
也可以访问到静态资源:
再次打包发现新建了一个cesiumStatic
目录存放cesium
静态资源:
这样就可以更优雅的使用Cesium
了:
4.3 简单概括viteStaticCopy
做的事情:
-
开发环境:映射访问,不复制 ➡️ 更快的开发体验
-
生产环境:实际复制 ➡️ 确保部署后可用
最后:
其实,无论你是使用原生 html
还是 vite
又或者是 webpack
,看 以下资料 就足以快速上手 Cesium
。本文更想探寻的是 "照着写" 背后的原因、"不这么写为什么不行" 以及 "还可以怎么写"。