Cesium 数据
影像数据:Bing、天地图、ArcGIS、OSM、WMTS、WMS等
地形数据:ArcGIS、谷歌、STK等
矢量数据:KML、KMZ、GeoJSON、TopoJSON、CZML
三维模型:GLTF、GLB(二进制glTF文件)
三维瓦片:3D Tiles(倾斜摄影、人工模型、 三维建筑物、CAD、BIM,点云数据等)
Cesium 坐标系统
-
WGS84弧度坐标系(Cartographic)
弧度= π/180×经纬度角度 -
笛卡尔空间直角坐标系(Cartesian3)
平面坐标系(Cartesian2)
4D笛卡尔坐标系(Cartesian4)
项目初始化
-
vite一个项目
-
npm i cesium@1.99 vite-plugin-cesium
-
配置插件
import cesium from 'vite-plugin-cesium' export default defineConfig({plugins: [vue(),vueDevTools(),cesium(),],
-
在
app.vue
中引入Cesiumimport * as Cesium from 'cesium' console.log(Cesium)
-
一个页面
<template><div id="cesiumContainer"></div> </template><script setup> import { onMounted } from 'vue' import * as Cesium from 'cesium'onMounted(() => {// 使用Cesium的Ion服务进行认证Cesium.Ion.defaultAccessToken = '';// 创建一个Viewer实例const viewer = new Cesium.Viewer('cesiumContainer', {// 使用默认的影像图层和地形图层terrainProvider: Cesium.createWorldTerrain({ requestWaterMask: true })}) }) </script><style scoped> #cesiumContainer {width: 100vw;height: 100vh;overflow: hidden; } </style>
Viewer基础操作
-
地图加载与初始化
通过创建一个Viewer对象来完成。这个对象包含了场景(scene)、相机(camera)和其他一些默认的控件。const viewer = new Cesium.Viewer('cesiumContainer', {terrainProvider: Cesium.createWorldTerrain({requestWaterMask: true,requestVertexNormals: true,}), })
-
相机控制
实现动态地图查看的关键部分-
setView
方法立即将相机定位到指定的位置,没有动画过渡
const position = Cesium.Cartesian3.fromDegrees(116.40, 39.90, 1000); viewer.camera.setView({destination: position,orientation: {heading: Cesium.Math.toRadians(0),pitch: Cesium.Math.toRadians(-90),roll: Cesium.Math.toRadians(0),}, });
-
flyTo
方法
让相机平滑地飞向指定位置,提供了动画效果viewer.camera.flyTo({destination: Cesium.Cartesian3.fromDegrees(120.0, 30.0, 2000000),duration: 3.0,orientation: {heading: Cesium.Math.toRadians(20),pitch: Cesium.Math.toRadians(-15),roll: 0.0,}, });
-
lookAt
方法
将相机指向一个特定的目标点,而不会改变当前的相机位置const target = Cesium.Cartesian3.fromDegrees(120.0, 30.0); viewer.camera.lookAt(target, new Cesium.HeadingPitchRange(0, - Cesium.Math.PI_OVER_TWO, 5000000));
-
-
坐标转换
-
经纬度转笛卡尔
const cartesian3 = Cesium.Cartesian3.fromDegrees(114.0, 30.0, 500000);
-
笛卡尔转经纬度
const cartographic = Cesium.Cartographic.fromCartesian(cartesian3); const longitude = Cesium.Math.toDegrees(cartographic.longitude); const latitude = Cesium.Math.toDegrees(cartographic.latitude);
-
实体与数据源
-
实体(Entity)
描述具有几何形状和属性的对象的基类-
添加实体
const pointEntity = viewer.entities.add({position: Cesium.Cartesian3.fromDegrees(103.1, 25.0),point: {color: Cesium.Color.YELLOW,pixelSize: 10,},name: 'Sample Point',description: 'This is a description for the sample point.' });
-
删除实体
viewer.entities.remove(pointEntity);
-
创建动态效果
定义一个回调函数,这个函数可以在每个帧中被CallbackProperty
调用,以动态地更新实体的属性// 定义一个回调函数,该函数将根据当前时间返回实体的位置 function positionCallback(time, result) {// 获取当前时间,并转换为JulianDatevar timestamp = Cesium.JulianDate.toDate(time);// 根据时间计算经度,这里假设每秒移动10度var longitude = Cesium.Math.toRadians(10 * timestamp.getSeconds());// 固定纬度值var latitude = Cesium.Math.toRadians(20);// 固定高度值var height = 100000.0;// 返回Cartesian3位置if (!Cesium.defined(result)) {result = new Cesium.Cartesian3();}result = Cesium.Cartesian3.fromRadians(longitude, latitude, height);return result; }// 创建一个CallbackProperty,该属性将在每一帧调用positionCallback函数 var positionProperty = new Cesium.CallbackProperty(positionCallback, false);// 添加一个点状实体到Viewer var pointEntity = viewer.entities.add({name: 'Dynamic point',position: positionProperty,point: {pixelSize: 10,color: Cesium.Color.YELLOW} });// 定位到实体 viewer.zoomTo(viewer.entities);
-
-
数据源(DataSources)
加载和管理地理数据的组件, 可以处理多种格式的数据-
加载GeoJSON数据
const geoJsonData = {"type": "FeatureCollection","features": [{"type": "Feature","geometry": {"type": "Point","coordinates": [-122.39, 47.5]}}] };const geoJsonPromise = Cesium.GeoJsonDataSource.load(geoJsonData); geoJsonPromise.then(function(dataSource) {viewer.dataSources.add(dataSource);viewer.zoomTo(dataSource); });
-
加载TopoJSON数据
const topoJsonPromise = Cesium.GeoJsonDataSource.load('path/to/topojson.data'); topoJsonPromise.then(function(dataSource) {viewer.dataSources.add(dataSource);viewer.zoomTo(dataSource); });
-
加载KML数据 (Google Earth)
const kmlPromise = Cesium.KmlDataSource.load('path/to/placemark.kml'); kmlPromise.then(function(dataSource) {viewer.dataSources.add(dataSource);viewer.zoomTo(dataSource); });
-
加载CZML数据
专为Cesium设计的动态数据格式, 使用JSON数组来描述随时间变化的图形属性const czmlPromise = Cesium.CzmlDataSource.load('path/to/document.czml'); czmlPromise.then(function(dataSource) {viewer.dataSources.add(dataSource);viewer.trackedEntity = dataSource.entities.getById('ID_of_Entity');// 允许相机自动跟踪数据源中的特定实体 });
-
图元(Primitive)
一种用于创建和操作三维几何形状的底层API, 面向三维图形开发者, 允许开发者直接控制几何体(Geometry)的创建和外观(Appearance)表现;
Entity API是数据驱动更高级一些
创建基本图元:
-
创建一个基本几何体对象(Primitive):
使用Cesium.Primitive构造函数创建一个新的几何体对象。 -
定义几何实例:
geometryInstances属性接受一个Cesium.GeometryInstance对象,这个对象包含几何体的具体信息。 -
创建椭圆形几何体(EllipseGeometry):
geometry属性是一个Cesium.EllipseGeometry对象,它定义了一个椭圆的几何形状。
rotation属性定义了椭圆的旋转角度,这里使用了Cesium.Math.PI_OVER_FOUR,表示旋转了45度。
vertexFormat定义了顶点格式,表示顶点包含位置和纹理坐标。 -
定义外观(EllipsoidSurfaceAppearance):
appearance属性接受一个Cesium.EllipsoidSurfaceAppearance对象,它定义了几何体的外观。
material属性定义了材质,这里使用了Cesium.Material.fromType方法,并传入了Stripe类型,表示使用条纹材质。 -
添加几何体到场景(Viewer):
使用viewer.scene.primitives.add(primitive)将创建的几何体添加到Cesium Viewer的场景中。
const primitive = new Cesium.Primitive({geometryInstances: new Cesium.GeometryInstance({geometry: new Cesium.EllipseGeometry({center: Cesium.Cartesian3.fromDegrees(-100.0, 20.0),semiMinorAxis: 500000.0,semiMajorAxis: 1000000.0,rotation: Cesium.Math.PI_OVER_FOUR,vertexFormat: Cesium.VertexFormat.POSITION_AND_ST}),}),appearance: new Cesium.EllipsoidSurfaceAppearance({material: Cesium.Material.fromType('Stripe'),}),
})
viewer.scene.primitives.add(primitive);
交互事件
ScreenSpaceEventHandler
类
-
点击事件
let viewer = new Cesium.Viewer('cesiumContainer', {terrainProvider: Cesium.createWorldTerrain()})let handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas)handler.setInputAction((event) => {// 返回一个笛卡尔坐标let position = viewer.scene.pickPosition(event.position)// 如果有这个坐标if (Cesium.defined(position)) {console.log(position)viewer.entities.add({position: position,point: {color: Cesium.Color.BLUE,pixelSize: 20,},})}console.log(viewer.entities)}, Cesium.ScreenSpaceEventType.LEFT_CLICK)
-
移动事件
let pickModellet viewer = new Cesium.Viewer('cesiumContainer', {terrainProvider: Cesium.createWorldTerrain()})// 添加建筑物const city = viewer.scene.primitives.add(new Cesium.Cesium3DTileset({url: Cesium.IonResource.fromAssetId(75343),}))viewer.flyTo(city)let handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);handler.setInputAction((event) => {// 拾取模型const pick = viewer.scene.pick(event.endPosition);if (pick) {if (pickModel) {pickModel.color = Cesium.Color.WHITE;}pick.color = Cesium.Color.ORANGERED;pickModel = pick;} }, Cesium.ScreenSpaceEventType.MOUSE_MOVE)
-
事件注销
handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK); //移除左键点击事件
综合应用
- 初始化Cesium Viewer
const viewer = new Cesium.Viewer('cesiumContainer', {terrainProvider: Cesium.createWorldTerrain(),baseLayerPicker: false, // 隐藏基础图层选择器shouldAnimate: true
})
- 3D Tiles格式加载三维模型
const cityModel = viewer.scene.primitives.add(new Cesium.Cesium3DTileset({url: Cesium.IonResource.fromAssetId(123456), // 替换为实际的模型IDmaximumScreenSpaceError: 16
}))
- 点击显示建筑物详细信息
viewer.screenSpaceEventHandler.setInputAction((event) => {const clickPosition = event.positionconst pickedObject = viewer.scene.pick(clickPosition)if (pickedObject && pickedObject instanceof Cesium.Cesium3DTileFeature) {const buildingInfo = pickedObject.getProperty('name')showBuildingInfo(buildingInfo) // 显示建筑物信息的自定义函数}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK)
- 创建粒子系统来模拟城市中夜晚的灯光
const particleSystem = new Cesium.ParticleSystem({image: 'path/to/particle-image.png',emitter: new Cesium.CircleEmitter({radius: 10}),emissionRate: 1,lifetime: 60,loop: true,modelMatrix: Cesium.Matrix4.multiplyByTranslation({Cesium.Transforms.eastNorthUpToFixedFrame(Cesium.Cartesian3.fromDegrees(103.1, 25.0, 1000)),new Cesium.Cartesian3(0, 0, 0),new Cesium.Matrix4()})
})
viewer.scene.primitives.add(particleSystem)