Cesium 源碼筆記[1] Viewer模塊實例化的大致過程 ver1.67

我原本想寫日記的,但是不太現實。

源碼下載

源碼可以從源碼包和發行包中的Source目錄中獲取。

Cesium的模塊化機制從1.63版本開始,由原來的RequireJs變為ES6。但有可能是原先設計耦合的問題,內部依舊是ES5實現。

入口:實例化Viewer時到底發生了什么

寫Cesium程序時,都寫過這一句:

let viewer = new Cesium.Viewer(dom)

或者這樣

let viewer = new Cesium.Viewer(dom, {
    terrainProvider: Cesium.createWorldTerrain()
})

那它究竟在后面發生了什么呢?

Viewer.js

定位到302行,Viewer的構造函數如下:

function Viewer(container, options) {
    ...
}

就從這個長達400多行的構造函數看起吧!

// 304~309行
if (!defined(container)) {
    throw new DeveloperError('container is required.');
}
container = getElement(container);

這一步,是看看DOM元素是否存在,使用getElement模塊判斷是domID或者是DOM元素變量,并返回。

工具模塊:defaultValue

// 310行
options = defaultValue(options, defaultValue.EMPTY_OBJECT);

這一步是判斷傳進來的options對象是否為空,如果為空,那就使用空對象預設值(defaultValue.EMPTY_OBJECT))。其中,defaultValue是一個重要的模塊,它判斷第一個參數如果是undefined,就把第二個參數作為它的值返回,如果不是undefined,那就返回它本身。

工具模塊:defined

// 312~313行
var createBaseLayerPicker = (!defined(options.globe) || options.globe !== false) && 
(!defined(options.baseLayerPicker) || options.baseLayerPicker !== false);

這一步通過defined模塊判斷構造參數options是否有globe屬性、baseLayerPicker屬性來決定是否創建底圖選擇器控件。defined模塊的作用就是,判斷傳入值是否定義,定義了就返回true。

329行將Viewer實例的this變量賦予給that變量。

331~344行是Viewer視圖底下的一堆空間的div DOM元素創建。

346~362行,利用defaultValue模塊和defined模塊

  • 判斷傳入參數options中scene3DOnly參數是否賦值,如果沒有則默認為false,即是否僅使用3d場景的意思;

  • 判斷傳入參數options中的時鐘模型屬性clockViewModel是否存在,來決定是用傳入的時鐘模型,亦或者是用系統的時鐘模型;

  • 判斷傳入參數options中是否定義了shouldAnimate屬性,如果定義了,則將時鐘的同名屬性設為同樣的值。

最初的一步: CesiumWidget創建

// Cesium.js 364~388行
var cesiumWidget = new CesiumWidget(cesiumWidgetContainer, {
    imageryProvider: createBaseLayerPicker || defined(options.imageryProvider) ? false : undefined,
    clock : clock,
    skyBox : options.skyBox,
    skyAtmosphere : options.skyAtmosphere,
    sceneMode : options.sceneMode,
    mapProjection : options.mapProjection,
    globe : options.globe,
    // ... 太長了不貼了
});

這一步和創建Viewer很像,但是它卻更接近數據承載體一步。

為了保證單元的完整性,CesiumWidget的實例化,后面再說。提前透露:高頻API,Scene、imageryProvider、Globe等均在這一步繼續創建。

其他的初始化

390~615行,是對Viewer的一些其他屬性的初始化,分別是界面上的一眾按鈕、時間軸等控件的初始化,以及事件總管理者(EventHelper模塊)的初始化、重要的DataSourceCollection/DataSourceDisplay的初始化。

在后面Viewer部分的筆記中,關于這些控件的初始化,還會繼續詳細展開。

DataSourceCollection/DataSourceDisplay屬于數據范圍,不列入Viewer部分的筆記中。

最后,將以上初始化的對象,全部注冊注冊為當前Viewer實例的屬性,并將其中一些對象例如dataSourceCollection的一些事件一并注冊到Viewer的原型上。

除了以上初始化之外,Cesium還默認為cesiumWidget注冊了屏幕操作事件的點擊、雙擊事件,方便初始化完成后能通過點擊來拾取場景中的Entity(場景Scene、實體Entity是數據范圍,不作詳細介紹了),這兩個事件使用cesiumWidget.screenSpaceEventHandler.setInputAction方法來注冊。這兩個事件位于構造函數的689~708行。

原型定義

工具方法:Object.defineProperties

這幾乎是每一個Cesium模塊都會做的一步,使用Object.defineProperties,為某個對象賦予某個屬性。

據說這個Object.defineProperties是近幾個版本才啟用的,之前js沒有這個方法時,是用Cesium.defineProperties的。

在Viewer.js模塊中的711~1292行,官方為Viewer的原型定義了一大批屬性,包括上文提及的初始化的多個對象、事件等,還包括上文創建的各個初始化的對象的一些屬性快捷連接,以便能在Viewer實例上直接訪問其他模塊的屬性。

例如你既能在Viewer上獲取camera,也能在Scene模塊獲取camera,只不過Viewer上返回的camera也要先訪問scene罷了。

隨后,在1294~1523行和1724~1858行,為Viewer的原型定義了一堆API文檔中能看到的公共方法;在1525~1703和1863~2056行為Viewer的原型定義了一堆私有方法。

導出Viewer模塊

最后,在2066行,使用es6語法導出Viewer構造函數。

版權所有。轉載請聯系我,B站/知乎/小專欄/博客園/CSDN @秋意正寒
http://www.jsfhjj.com/onsummer/p/12571971.html

posted @ 2020-03-30 02:39  秋意正寒  閱讀(...)  評論(...編輯  收藏
最新chease0ldman老人