Cesium的api非常烦杂,我们从核心说起。搭建一个三维Web程序所需要的最基本的东西有哪些呢? 我们需要一个div,然后基于此div创建canvas,引入webgl环境。 每个三维渲染引擎都有各自不同的方法或者类来做这件事情,Cesium则是通过CesiumWidget这个类创建。如下所示:
html代码部分
<style>
@import url(../templates/bucket.css);
</style>
<div id="cesiumContainer" class="fullSize"></div>
<div id="loadingOverlay"><h1>Loading...</h1></div>
<div id="toolbar"></div>
js代码部分
// Cesium.CesiumWidget is similar to Cesium.Viewer, but
// is trimmed down. It is just a widget for the 3D globe;
// it does not include the animation, imagery selection,
// and other widgets, nor does it depend on the third-party
// Knockout library.
const widget = new Cesium.CesiumWidget("cesiumContainer");
http://localhost:8080/Apps/Sandcastle/index.html?src=Cesium%20Widget.html
这个示例在Cesium的Sandcastle当中,但是非常不起眼。很多人容易忽略掉。因为这几乎是唯一使用CesiumWidget来创建Cesium三维应用的示例了。但这并不代表它不重要。相反,它才是真正创建Cesium三维窗口的核心类。
如果是已经使用Cesium进行开发过的小伙伴们,可能对此类并不熟悉。毕竟Cesium中最常用的是Viewer、Entity这些类。不过这些类内部结构比较复杂,我们还是希望先忽略这两个类。等把底层的框架说清楚以后,再回头看着两个类,会对Cesium的理解更加深刻。
CesiumWidget构造时,手里拿了一个叫cesiumContainer
的字符串,它实际上是一个div的id。这个div好比一个舞台,CesiumWidget有了这个舞台,就开始创建一系列子div,还是canvas对象,据此搭建了整个三维场景。
CesiumWidget内部创建的对象主要有以下几个部分,如图所示:
clock用来记录时间,毕竟三维场景需要进行动态展示,需要通过时间来确定某一帧的绘制内容。
container则是构造函数的参数,也就是传入的div,这里记录一下。
canvas则是在container上构建的Canvas类的对象,可以据此获取WebGL绘制的画笔。
screenSpaceEventHandler则是对Canvas对象上各种鼠标的交互事件的封装,方便传递给三维场景。
三维场景干之后可以据此改变相机姿态等。 scene则承载着整个三维场景中的对象。
Scene中有一些内置的图元对象:地球(globe)、skyBox(天空盒)、sun(太阳)、moon(月亮)等等; 另外还有两个用来由用户自行控制存放对象的数组:primitives和groundPrimitives。
图元是Cesium用来绘制三维对象的一个独立的结构。图元类有:Globe、Model、Primitive、BillboardCollection、ViewportQuad等。
Globe绘制的是全球地形,它需要两个东西,一个是地形高程信息,另外一个是影像图层,也就是地球的表皮。影像图层可以叠加多个,但是地形高程只能有一个。整个地形的绘制也是渐进式的,即视线看到的地方才会去调度相关的地形高程信息,找到对应位置的地形影像贴上。然而Globe只是一个图元。由此可见一个图元可以相当复杂。
需要注意的地方:
整个CesiumWidget的结构如下所示: