我本來想寫日記的,可是不太現實。html
源碼能夠從源碼包和發行包中的Source目錄中獲取。es6
Cesium的模塊化機制從1.63版本開始,由原來的RequireJs變爲ES6。但有多是原先設計耦合的問題,內部依舊是ES5實現。dom
寫Cesium程序時,都寫過這一句:ide
let viewer = new Cesium.Viewer(dom)
或者這樣模塊化
let viewer = new Cesium.Viewer(dom, { terrainProvider: Cesium.createWorldTerrain() })
那它究竟在後面發生了什麼呢?函數
定位到302行,Viewer的構造函數以下:工具
function Viewer(container, options) { ... }
就從這個長達400多行的構造函數看起吧!ui
// 304~309行 if (!defined(container)) { throw new DeveloperError('container is required.'); } container = getElement(container);
這一步,是看看DOM元素是否存在,使用getElement模塊判斷是domID或者是DOM元素變量,並返回。this
// 310行 options = defaultValue(options, defaultValue.EMPTY_OBJECT);
這一步是判斷傳進來的options對象是否爲空,若是爲空,那就使用空對象預設值(defaultValue.EMPTY_OBJECT)
)。其中,defaultValue
是一個重要的模塊,它判斷第一個參數若是是undefined,就把第二個參數做爲它的值返回,若是不是undefined,那就返回它自己。設計
// 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屬性,若是定義了,則將時鐘的同名屬性設爲一樣的值。
// 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行。
這幾乎是每個Cesium模塊都會作的一步,使用Object.defineProperties,爲某個對象賦予某個屬性。
聽說這個Object.defineProperties是近幾個版本才啓用的,以前js沒有這個方法時,是用Cesium.defineProperties的。
在Viewer.js模塊中的711~1292行,官方爲Viewer的原型定義了一大批屬性,包括上文說起的初始化的多個對象、事件等,還包括上文建立的各個初始化的對象的一些屬性快捷鏈接,以便能在Viewer實例上直接訪問其餘模塊的屬性。
例如你既能在Viewer上獲取camera,也能在Scene模塊獲取camera,只不過Viewer上返回的camera也要先訪問scene罷了。
隨後,在12941523行和17241858行,爲Viewer的原型定義了一堆API文檔中能看到的公共方法;在15251703和18632056行爲Viewer的原型定義了一堆私有方法。
最後,在2066行,使用es6語法導出Viewer構造函數。
版權全部。轉載請聯繫我,B站/知乎/小專欄/博客園/CSDN @秋意正寒
http://www.javashuo.com/article/p-fbgfakki-kr.html