本文为稀土掘金技术社区首发签约文章,14天内禁止转载,14天后未获授权禁止转载,侵权必究!
哈喽,大家好 我是
xy👨🏻💻。这篇文章是Cesium 三维地球可视化从入门到进阶专栏的第一篇,从今天起,让我带着各位一起探索CesiumJS的编程世界吧
前言
🎯 从今天起开始陆续的更新 Cesium 三维地球可视化从入门到进阶专栏的系列文章了, 如果你也对 三维可视化比较感兴趣的话,欢迎关注我一起学习
🎯 本次专栏所有案例都基于 Vue3 + Vite3 + TypeScript + CesiumJS 开发,并且所有案列的代码都会统一放到 github仓库中,开放给大家 免费学习使用
🎯 这里奉上 📚Github 仓库地址:https://github.com/xushanpei/Cesium_Study_Cases
CesiumJS 概述
CesiumJS 是一个用于显示 三维地球和 地图的开源 js 库。支持 3D, 2.5D, 2D 形式的地图展示,它可以用来显示海量 三维模型数据、影像数据、地形高程数据、矢量数据等等。同时也可以自行 绘制图形,高亮区域等,且支持绝大多数的浏览器和移动端
主要功能介绍
- 使用
3d tiles格式流式加载各种不同的3d数据,包含倾斜摄影模型、三维建筑物、CAD和BIM的外部和内部,点云数据。并支持样式配置和用户交互操作。 - 全球高精度
地形数据可视化,支持地形夸张效果、以及可编程实现的等高线和坡度分析效果。 - 支持多种资源的图像图层,包括
WMS,TMS,WMTS以及时序图像。图像支持透明度叠加、亮度、对比度、GAMMA、色调、饱和度都可以动态调整。 - 支持标准的
矢量格式KML、GeoJSON、TopoJSON、以及矢量的贴地效果。 - 三维模型支持
gltf2.0标准的PRB材质、动画、蒙皮和变形效果。 - 使用
CZML支持动态时序数据的展示。 - 支持各种几何体:
点、线、面、标注、公告牌、立方体、球体、椭圆体、圆柱体、走廊、管径、墙体。 - 可视化效果包括:基于太阳位置的
阴影、自身阴影、柔和阴影。 - 支持
大气、雾、太阳、阳光、月亮、星星、水面。 - 粒子特效:
烟、火、火花。 地形、模型、3d tiles模型的面裁剪。- 对象
点选和地形点选。 - 支持鼠标和触摸操作的
缩放、渲染、惯性平移、飞行、任意视角、地形碰撞检测。 - 支持
3d地球、2d地图、2.5d哥伦布模式。3d视图可以使用透视和正视两种投影方式。 - 支持
点、标注、公告牌的聚集效果。
基础环境搭建
Vue3 环境搭建
首先确保你安装了 Node.js(Node 安装过程这里不做过多讲解,直接官网下载安装即可),然后在 命令行中 运行以下命令:
npm init vue@latest
复制代码
这一指令将会安装并执行 create-vue,它是 Vue 官方的项目脚手架工具。你将会看到一些诸如 TypeScript 和 测试支持之类的可选功能提示, 这里按照个人需求安装选择对应的功能即可:
✔ Project name: … <cesium-study-cases>
✔ Add TypeScript? … No / Yes
✔ Add JSX Support? … No / Yes
✔ Add Vue Router for Single Page Application development? … No / Yes
✔ Add Pinia for state management? … No / Yes
✔ Add Vitest for Unit testing? … No / Yes
✔ Add Cypress for both Unit and End-to-End testing? … No / Yes
✔ Add ESLint for code quality? … No / Yes
✔ Add Prettier for code formatting? … No / Yes
Scaffolding project in ./<your-project-name>...
Done.
复制代码
更多的项目配置以及使用教程,可以参考我之前的写的文章:
🔥Vite2 + Vue3 + TypeScript + Pinia 搭建一套企业级的开发脚手架
🔥Vue3.x script setup 语法糖详解,助力快速上手 Vue3.x
安装 Cesium
目前 Vite 项目下安装 CesiumJS 有两种方式:
- 直接到官方
下载源码引入到项目中使用 npm方式结合使用Vite插件vite-plugin-cesium来安装
下载源码安装
打开官网: https://www.cesium.com/ => Platform => CesiumJS
点击 下载,下载完成后 解压,拷贝 Build 目录下的 Cesium 下的所有内容到项目的 public 目录下即可
入口文件 index.html 中引入:
<link rel="stylesheet" href="/cesium/Widgets/widgets.css" />
<script src="/cesium/Cesium.js"></script>
复制代码
npm 下载安装
npm i cesium
npm i -D vite-plugin-cesium
复制代码
vite.config.ts 中配置:
import cesium from "vite-plugin-cesium"; // 引入插件
export default defineConfig({
plugins: [cesium()],
});
复制代码
以上两种方式任选一种安装即可,本次项目中的采用的是 第二种 npm 安装的方式
让 VScode 可以提示 Cesium 配置
npm i -S @types/cesium
复制代码
好了,基础的环境配置好了,下面来创建一个属于自己的三维地球吧!!!
创建一个属于自己的三维地球
申请 Token
在动手写代码之前,记得先去 Cesium 申请一个 Token。
Cesium 建议开发者在开发前申请一个单独的 令牌(token),这个 Token 的作用是可以在 Cesium项目中调用 地图和 地形服务。
打开 https://cesium.com/ion 网址注册登录自己的账号
在 Access Tokens界面 Create token,
给自己的 Token 定义一个名称,然后根据自己的需求 勾选对应的功能即可
创建成功后复制 Token 保存下来
这里我直接在项目的文件夹下新建一个 utils 文件夹, 在 utils 文件夹下新建一个 Token.ts ,专门用来保存我们的 Token
创建三维地球
1.在 src => view 目录下创建一个 init.vue , 初始化出一个组件模板并且引入 Cesium
import Cesium from "cesium";
复制代码
引入成功后运行发现报错了:
这个错误的大致意思是 cesium.js 没有提供名为“default”的导出, 解决方式有两种:
- 全量导出,
as重命名
import * as Cesium from "cesium";
复制代码
- 直接
解构出需要的模块名称, 不知道什么是解构的建议看看es6
import { Viewer } from "cesium";
复制代码
2.创建容器,初始化 Viewer
import cesium from 'vite-plugin-cesium';
<template>
<div id="cesiumContainer"></div>
</template>
<script setup lang="ts">
import { onMounted } from "vue";
import * as Cesium from "cesium";
import TOKEN from "../utils/Token";
// Token 设置
Cesium.Ion.defaultAccessToken = TOKEN;
// Viewer
let viewer = null;
onMounted(() => {
initViewer();
});
const initViewer = () => {
viewer = new Cesium.Viewer("cesiumContainer");
};
</script>
复制代码
这样一个简单的 cesiumJS 三维数字地球就运行起来了
基础要素讲解
任何 Cesium 应用程序的基础都是 Viewer,Viewer 是一个带有多种功能的可交互的三维数字地球的容器,同时初始化界面也默认自带了一些组件,其初始化场景及组件数字标号如下图所示:
每一个组件的描述如下:
Geocoder:查找位置工具,查找到之后会将镜头对准找到的地址HomeButton:首页位置,点击之后将视图跳转到默认全球视角SceneModePicker:选择视角的模式,3D,2D,2.5D 哥伦布视图BaseLayerPicker:图层选择器,选择要显示的地图服务和地形服务NavigationHelpButton:导航帮助按钮,显示默认的地图控制帮助Animation:动画器件,控制视图动画的播放速度CreditsDisplay:展示商标版权和数据归属Timeline:时间轴,指示当前时间,并允许用户跳到特定的时间FullscreenButton:全屏按钮
Viewer 中常用配置详解如下:
viewer = new Cesium.Viewer("cesiumContainer", {
animation: true, //是否创建动画小器件,左下角仪表
baseLayerPicker: true, //是否显示图层选择器
fullscreenButton: true, //是否显示全屏按钮
vrButton: true, // 用于切换 VR 模式的单个按钮小部件。
geocoder: true, // //是否显示geocoder小器件,右上角查询按钮
homeButton: true, //是否显示Home按钮
infoBox: true, //是否显示信息框
sceneModePicker: true, //是否显示3D/2D选择器
selectionIndicator: true, //是否显示选取指示器组件
timeline: true, //是否显示时间轴
navigationHelpButton: true, //是否显示右上角的帮助按钮
navigationInstructionsInitiallyVisible: true,
scene3DOnly: false, //如果设置为true,则所有几何图形以3D模式绘制以节约GPU资源
shouldAnimate: false, // 初始化是否开始动画
clockViewModel: undefined, // 一个视图模型,它为用户界面提供 Clock
selectedImageryProviderViewModel: undefined, //当前图像图层的显示模型,仅baseLayerPicker设为true有意义
selectedTerrainProviderViewModel: undefined, //当前地形图层的显示模型,仅baseLayerPicker设为true有意义
skyAtmosphere: new Cesium.SkyAtmosphere(), // 围绕提供的椭球体边缘绘制的大气
fullscreenElement: document.body, //全屏时渲染的HTML元素,
useDefaultRenderLoop: true, //如果需要控制渲染循环,则设为true
targetFrameRate: undefined, //使用默认render loop时的帧率
showRenderLoopErrors: false, //如果设为true,将在一个HTML面板中显示错误信息
automaticallyTrackDataSourceClocks: false, //自动追踪最近添加的数据源的时钟设置
contextOptions: {}, //传递给Scene对象的上下文参数(scene.options)
sceneMode: Cesium.SceneMode.SCENE3D, //初始场景模式
mapProjection: new Cesium.WebMercatorProjection(), //地图投影体系
globe: undefined, // 在场景中渲染的地球仪,包括其地形 ( Globe#terrainProvider ) 和图像图层 ( Globe#imageryLayers )
orderIndependentTranslucency: true,
dataSources: new Cesium.DataSourceCollection(), //需要进行可视化的数据源的集合
projectionPicker: undefined, //ProjectionPicker 是用于在透视和正交投影之间切换的单按钮小部件。
// imageryProviderViewModels: Cesium.createDefaultImageryProviderViewModels(), //图层选择器,可供BaseLayerPicker选择的图像图层ProviderViewModel数组
// terrainProviderViewModels: Cesium.createDefaultTerrainProviderViewModels(), //地形选择器,可供BaseLayerPicker选择的地形图层ProviderViewModel数组
// imageryProvider: new Cesium.OpenStreetMapImageryProvider({
// credit: "",
// url: "Custom url",
// }), //图像图层提供者,仅baseLayerPicker设为false有意义
terrainProvider: new Cesium.EllipsoidTerrainProvider(), //地形图层提供者,仅baseLayerPicker设为false有意义
});
复制代码
虽然 Cesium 自带的一些组件功能都比较强大,但是奈何大多数情况下,我们都需要重写这些组件来适配我们的项目, 所以很多时候都是把这些小组件隐藏起来
修改天空背景(skyBox)
Cesium 自带的天空盒子背景偏黑色, 天空盒子的贴图是6张(也叫立方体贴图),分别对应6个方向的星空背景贴图。
想象一下,一个立方体盒子将天球包围,从球心到球面上任意一点的连线延伸出去必然与立方体盒子的一个面相交,从而将球面上的一个点映射到立方体的一个面上。最终完整的天球映射到立方体盒子的两个面上,形成6张正方形的图片。
把提前准备好的天空盒图片放到 /public/skyBox 文件夹下,Viewer 中增加如下配置即可:
//用于渲染星空的SkyBox对象
skyBox: new Cesium.SkyBox({
sources: {
positiveX: "/skyBox/00h+00.jpg",
negativeX: "skyBox/12h+00.jpg",
positiveY: "/skyBox/06h+00.jpg",
negativeY: "/skyBox/18h+00.jpg",
positiveZ: "/skyBox/06h+90.jpg",
negativeZ: "/skyBox/06h-90.jpg",
},
})
复制代码
效果如下展示:
去除版权信息
viewer.cesiumWidget.creditContainer.style.display = "none";
复制代码
增加太阳光照效果
viewer.scene.globe.enableLighting = true;
复制代码
实现昼夜联动效果
// 加载昼夜联动
const loadEarthAtNight = () => {
const dynamicLighting = true;
viewer.clock.multiplier = 4000;
const imageryLayers = viewer.imageryLayers;
const nightLayer = imageryLayers.get(0);
const dayLayer = imageryLayers.addImageryProvider(
new Cesium.IonImageryProvider({
assetId: 3845,
})
);
imageryLayers.lowerToBottom(dayLayer);
updateLighting(dynamicLighting, nightLayer, dayLayer);
};
// 更新光照效果
const updateLighting = (
dynamicLighting: any,
nightLayer: any,
dayLayer: any
) => {
dayLayer.show = dynamicLighting;
viewer.scene.globe.enableLighting = dynamicLighting;
viewer.clock.shouldAnimate = dynamicLighting;
nightLayer.dayAlpha = dynamicLighting ? 1.0 : 1.0;
};
复制代码
🎯 这篇文章是 Cesium 三维地球可视化从入门到进阶 专栏的开篇文章,主要是给一些没有接触过 Cesium 的并且想要入门三维可视化的同学的一篇入门教程
🎯 在后续的文章中, 将会分享更多的实践案例,如果你也对 三维可视化比较感兴趣的话,欢迎关注我一起学习
🎯 Github 仓库地址:https://github.com/xushanpei/Cesium_Study_Cases
写在最后
公众号:前端开发爱好者专注分享web前端相关技术文章、视频教程资源、热点资讯等,如果喜欢我的分享,给 🐟🐟 点一个赞👍 或者 ➕关注都是对我最大的支持。
大家好,我 xy,是一名前端 🤫 爱好:瞎折腾
如果你也是一名瞎折腾的前端欢迎加我微信交流哦...