Cesium应用篇:3控件(3)SelectionIndicator InfoBox
假設(shè)這樣一個(gè)場(chǎng)景,用戶在Cesium球上加載了一個(gè)GeoJson文件(DataSource),里面是全美國(guó)所有州的Geometry信息(Entity),疊加到球面后,你自然會(huì)有一種沖動(dòng),點(diǎn)擊某一個(gè)州,了解這個(gè)州的基本信息。場(chǎng)景如下圖所示:
這個(gè)點(diǎn)擊行為,對(duì)應(yīng)的是選擇控件(SelectionIndicator),而呈現(xiàn)信息的載體,就是信息框控件(InfoBox)。
如上是一個(gè)簡(jiǎn)單的邏輯關(guān)系,可見Viewer.SelectEntity屬性起到了承上啟下的作用。首先,Viewer模塊負(fù)責(zé)UI的事件交互,比如鼠標(biāo)點(diǎn)擊或者雙擊,則會(huì)觸發(fā)對(duì)應(yīng)事件,判斷當(dāng)前的鼠標(biāo)事件是否選中了Entity,如果選中,則更新Viewer.SelectEntity屬性。
如上,可以看到在Cesium源碼中,目前綁定了兩個(gè)事件,一個(gè)是鼠標(biāo)左鍵單擊,選中該Entity,一個(gè)是鼠標(biāo)左鍵雙擊,則會(huì)追蹤到該位置。當(dāng)然,如果你想要增加或者修改某個(gè)事件,則可以修改screenSpaceEventHandler的內(nèi)容。可以參考 screenSpaceEventHandler,比如很多人希望取消雙擊效果,則可以調(diào)用:viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
而無(wú)論是單擊還是雙擊,內(nèi)部都是通過(guò)pickEntity獲取選中的Entity,該方法內(nèi)部通過(guò)ID作為唯一標(biāo)識(shí),判斷是否選中某一Entity,具體實(shí)現(xiàn)我們以后在詳細(xì)討論。而在單擊中,會(huì)調(diào)用Viewer.SelectEntity的Set方法,此時(shí),當(dāng)狀態(tài)發(fā)生變化時(shí)(選中或消失),都會(huì)觸發(fā)選擇控件的動(dòng)畫效果:
如上就是一個(gè)Entity從鼠標(biāo)選中,事件的觸發(fā)以及屬性信息的顯示的大致過(guò)程。
但Cesiu支持實(shí)時(shí)性的InfoBox狀態(tài)更新,也就是說(shuō),在每一幀,我們都可以更新選擇控件和信息框控件的狀態(tài),而這,就要從Viewer.prototype._onTick說(shuō)起。
首先,Viewer.prototype._onTick由Clock.onTick事件觸發(fā),而時(shí)鐘本身在每一幀都會(huì)觸發(fā)onTick事件,因此Viewer也可以通過(guò)onTick來(lái)實(shí)現(xiàn)自身的更新。
機(jī)智的你一眼就看到了time參數(shù),原來(lái)如此。這時(shí),根據(jù)time時(shí)間,我們獲取對(duì)應(yīng)的description,字符串類型,本身就是一個(gè)div,然后賦給infoBoxViewModel.description進(jìn)而實(shí)現(xiàn)InfoBox控件的實(shí)時(shí)更新。
通常,每一個(gè)Entity的description都是固定內(nèi)容,不需要根據(jù)時(shí)間等變換,而如果對(duì)實(shí)時(shí)性有一定要求,或者需要自定義效果,則需要匿名函數(shù)來(lái)實(shí)現(xiàn)回調(diào)方法。在這看不見的地方,主要是createPropertyDescriptor,Property兩者間錯(cuò)綜復(fù)雜的關(guān)系…
如上是Entity中description的屬性定義,通過(guò)createPropertyDescriptor把Entity. description封裝成Property,提供了Set和Get方法,方便該屬性的調(diào)用。這里createPropertyDescriptor會(huì)根據(jù)屬性賦值來(lái)選擇具體的Property子類來(lái)滿足不同需求,稍后在介紹完P(guān)roperty在詳細(xì)解釋這一部分。
對(duì)于Property,則會(huì)調(diào)用getValueOrDefault方法,獲取該Entity的description,獲取每一個(gè)Entity對(duì)應(yīng)的描述信息,這里,每一個(gè)Property都需要提供一個(gè)getValue的標(biāo)準(zhǔn)方法,這也是每一個(gè)Property子類必須要實(shí)現(xiàn)的方法:
而Property有很多子類,但在InfoBox中,主要涉及到CallbackProperty和ConstantProperty兩種類型,通過(guò)命名我們不難看出,前者是一種回調(diào)方式,而后者則是一個(gè)常量。
好了,對(duì)Property有了一個(gè)基本認(rèn)識(shí)后,我們?cè)诳纯碿reatePropertyDescriptor的具體實(shí)現(xiàn):
高亮處代碼,不難看出,在創(chuàng)建時(shí)優(yōu)先考慮CallbackProperty的屬性,如果用戶沒(méi)有采用這種屬性,此時(shí),value為String類型而不是Property,所以沒(méi)有實(shí)現(xiàn)value. getValue方法,則將value(String)封裝為ConstantProperty。所以,constant常量的方式非常簡(jiǎn)單,直接賦值即可:
Entity.description = “<div> description</div>”;
可我偏要用回調(diào)的方式,如何破?我們看看GeoJsonDataSource中是如何實(shí)現(xiàn)的。
首先,你要實(shí)現(xiàn)一個(gè)匿名函數(shù),如上,實(shí)現(xiàn)一個(gè)describe方法,其中,因?yàn)槭悄涿瘮?shù),所以可以隨時(shí)獲取到該Entity的所有屬性的Key-Value,可以根據(jù)自己的需要來(lái)創(chuàng)建對(duì)應(yīng)的DIV,另外,該匿名函數(shù)也提供time參數(shù),滿足對(duì)實(shí)時(shí)性的需求。
如果,萬(wàn)事俱備,我們就可以開心的創(chuàng)建一個(gè)CallbackProperty了:
而CallbackProperty的getValue的實(shí)現(xiàn)如下,通過(guò)該方法,可以把Entity的description屬性,通過(guò)CallbackProperty,以RunTime的方式傳遞給InfoBox,如此,通過(guò)CallbackProperty可以實(shí)現(xiàn)動(dòng)態(tài)顯示InfoBox信息的方式:
基本上,InfoBox的實(shí)現(xiàn)大致如此,可以看到,Cesium的InfoBox的還是很成熟的,盡可以的在無(wú)編碼的情況下顯示Entity的屬性,同時(shí),也能滿足自定義的擴(kuò)展,并能夠滿足實(shí)時(shí)性的要求,而且封裝的很優(yōu)雅,也很簡(jiǎn)單,真的不是隨便就能寫來(lái)的……
光說(shuō)不練假把式,寫了這么多,相見ifoBox.html,,基于本文涉及到的知識(shí)點(diǎn),實(shí)現(xiàn)了自定義InfoBox內(nèi)容,并可以通過(guò)chart實(shí)現(xiàn)動(dòng)態(tài)效果。具體代碼參考infobox.html范例
總結(jié)
以上是生活随笔為你收集整理的Cesium应用篇:3控件(3)SelectionIndicator InfoBox的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 湖工微型计算机及原理题目,2017年湖北
- 下一篇: SQL SERVER 2000数据库置疑