Geocoder是一個非常簡單的控件,但也是非常常用且實用的控件,顧名思義,Geocoder就是地理編碼的意思,而平常我們經常會查詢一些地物,也就是常用的POI搜索,就是Geocoder的功勞。
首先,該控件支持經緯度定位,比如如下,是北京京洲世家小區的經緯度,輸入后可以定位至該點,如上圖所示。但是在天朝,有一種坐標叫做火星坐標。換句話說,如果你是在高德,百度等國內數據中獲取的POI經緯度,該經緯度是經過偏移的,而我們的三維球通常都是用Bing,天地圖等沒有偏移的影像,這樣就會導致地物的不匹配,還要,我們只需要糾偏POI就可以。范例里面有驚喜,自己看geocoder范例吧。
另外,Cesium采用的是Bing的地理編碼和POI檢索,需要Key,而且國內的數據,畢竟是中文檢索,Bing在這點上有些水土不服的,所以,下面我們試着用SuperMap的POI服務來替代(當然,你也可以用其他的,比如高德,百度等,但需要申請Key,我申請了也不知道為何說我的plat不支持,想到范例的簡單性,發現只有SuperMap的最簡單易用,也算一個無奈之舉吧。)
一個很不幸的事實是,Cesium沒想到用戶想要更換Geocoder的服務,所以並沒有提供對應的接口來方便我們的擴展,不過,畢竟是JavaScript嗎,只要深挖掘,什么都能替換之。
如上圖,我們需要改寫的就是searchCommand函數,盡管geocoder只提供了get接口。這里有兩個邏輯,第一個就是geocode,就是POI的查詢,另一個是正在查詢的狀態下,則會中斷正在進行的查詢操作。我們直接把GeocoderViewModel中的cancelGeocode函數拿來重用即可。而geocode則是需要重寫的重點函數。
直接輸入經緯度定位是很不錯的功能,所以要保留,這段代碼就留着。下面,就要開始替換Bing的POI檢索了。先看看超圖的POI檢索服務:
輸入京洲世家,為什么總要輸入這個?總比輸一個故宮博物院好吧。點擊查詢,我們就可以獲取其對應的url和json結果。
知道了url的規范后,通過Cesium構造一個Promise來發送請求:
返回的結果如下:
有了返回值,我們就需要解析里面的內容,並講這些POI信息構造成Entity,保存到Viewer中。同樣,這里的經緯度是偏移后的,我們需要做一個糾偏處理。
這里還有一個小技巧,我們每次查詢時,都需要清除上一次查詢的對象,所以我們需要在Geocoder中保存一份當前查詢POI的Entity對象,方便下次查詢后的刪除,而刪除是通過id的,所以需要付給一個唯一的ID值,我覺得通過Clock獲取當前時間是一個不錯的方式。
另外,為了能夠讓Entity在點擊時獲取其描述信息,我們也需要指定Entity的description,在geocoder.html范例中,采用了最簡單的ConstantProperty,如果對這一塊不清楚的,可以參考InfoBox控件篇,里面對Property有一個較為詳細的介紹。具體代碼如下:
至此,我們對Geocoder有了一個較為詳細的認識,同時也擴展Geocoder控件,能夠指定其他的POI服務來滿足自己的需要,並實現了對查詢后的POI構造並管理Entity的功能,更好的展現查詢后的結果。另外,由於火星坐標的原因,會有匹配不准確的情況,這里通過糾偏也解決了這一實際應用的問題。奉上一個范例的效果圖,Geocoder的介紹就到這里。