Cesium中級教程4 - 空間數(shù)據(jù)可視化(二)

Cesium中文網(wǎng):http://cesiumcn.org/ | 國內(nèi)快速訪問:http://cesium.coinidea.com/

Viewer中的Entity功能

讓我們看看Viewer為操作entities提供出來的功能函數(shù)。

選中和描述

點擊Viewer中的entity將在entity的位置上呈現(xiàn)SelectionIndicator控件,提供一個InfoBox用于呈現(xiàn)更多的信息。我們可以設(shè)置name,來定義InfoBox的標題。我們也以HTML樣式來提供Entity.description的屬性。

wyoming.name = 'wyoming';
wyoming.description = '\
<img\
  width="50%"\
  style="float:left; margin: 0 1em 1em 0;"\
  src="http://cesium.com/docs/tutorials/creating-entities/Flag_of_Wyoming.svg"/>\
<p>\
  Wyoming is a state in the mountain region of the Western \
  United States.\
</p>\
<p>\
  Wyoming is the 10th most extensive, but the least populous \
  and the second least densely populated of the 50 United \
  States. The western two thirds of the state is covered mostly \
  with the mountain ranges and rangelands in the foothills of \
  the eastern Rocky Mountains, while the eastern third of the \
  state is high elevation prairie known as the High Plains. \
  Cheyenne is the capital and the most populous city in Wyoming, \
  with a population estimate of 63,624 in 2017.\
</p>\
<p>\
  Source: \
  <a style="color: WHITE"\
    target="_blank"\
    >Wikpedia</a>\
</p>';
image

InfoBox中展示的所有HTML是沙盒式的。這組織了外部數(shù)據(jù)源帶有惡意的注入到Cesium的應(yīng)用程序中。為了在描述中運行JavaScript或瀏覽器插件,訪問沙盒中的iframe通過viewer.infoBox.frame屬性。參考該文 可以獲得更多的信息用于控制iframe中的沙盒。

Camera控制

使用iewer.zoomto命令查看特定Entity。還有一個viewer.flyto方法,用于對Entity執(zhí)行動畫Camera飛行。這兩種方法都可以傳遞給EntityEntityCollectionDataSource或?qū)嶓w數(shù)組。

任何一種方法都會計算所有提供的實體的視圖。默認情況下,Camera朝向北方,并從45度角向下看。通過傳入HeadingPitchrange自定義此項。

var heading = Cesium.Math.toRadians(90);
var pitch = Cesium.Math.toRadians(-30);
viewer.zoomTo(wyoming, new Cesium.HeadingPitchRange(heading, pitch));

[圖片上傳失敗...(image-ae8bb6-1558490847491)]

zoomToflyTo都是異步函數(shù);也就是說,它們不能保證在返回之前完成。例如,飛行到Entity會在許多動畫幀后發(fā)生。這兩個功能都返回Promises,可用于計劃飛行或縮放完成后要執(zhí)行的功能。用下面的代碼片段替換示例中的zoomTo。這架飛機飛往懷俄明州,并在飛行結(jié)束后選中它。

viewer.flyTo(wyoming).then(function(result){
    if (result) {
        viewer.selectedEntity = wyoming;
    }
});

如果航班飛行成功完成,則傳遞給回調(diào)函數(shù)的結(jié)果參數(shù)將為true;如果航班被取消,則結(jié)果參數(shù)將為false,即,在此航班完成之前,用戶啟動了另一個航班或縮放;或者,由于目標沒有相應(yīng)的可視化效果,即沒有可縮放的對象。

有時,特別是在處理時間動態(tài)數(shù)據(jù)時,我們希望Camera聚焦跟隨一個entity而不是地球的中心。可以通過設(shè)置viewer.trackedEntity完成。跟蹤實體需要設(shè)置position

wyoming.position = Cesium.Cartesian3.fromDegrees(-107.724, 42.68);
viewer.trackedEntity = wyoming;

停止跟蹤需要設(shè)置viewer.trackedEntityundefined或遠離entity雙擊屏幕即可。調(diào)用zoomToflyTo也可以取消跟蹤。

管理Entities

EntityCollection是用于管理和監(jiān)視一組實體的關(guān)聯(lián)數(shù)組。viewer.entitiesEntityCollectionEntityCollection包括用于管理實體的方法,如addremoveremoveAll

有時我們需要更新我們以前創(chuàng)建的實體。所有實體實例都有一個唯一的id,可用于從集合中檢索實體。我們可以為實體指定一個ID,否則將自動生成一個ID。

viewer.entities.add({
    id : 'uniqueId'
});

使用getByiId檢索實體。如果不存在具有提供的ID的實體,則返回undefined

var entity = viewer.entities.getById('uniqueId');

要獲取實體或創(chuàng)建新實體(如果不存在),請使用getOrCreateEntity

var entity = viewer.entities.getOrCreateEntity('uniqueId');

手動創(chuàng)建新實體,然后使用add將其添加到集合中。如果集合中已存在具有相id的實體,則此方法將拋出異常。

var entity = new Entity({
    id : 'uniqueId'
});
viewer.entities.add(entity);

EntityCollection的功能使用CollectionChanged事件發(fā)光。當在集合中添加、刪除或更新實體時,會通知監(jiān)聽器。

使用Sandcastle中的[Geometry Showcase]
(https://cesiumjs.org/Cesium/Build/Apps/Sandcastle/index.html?src=Geometry%20and%20Appearances.html&label=Showcases) 示例。在創(chuàng)建viewer的行后粘貼以下代碼。

function onChanged(collection, added, removed, changed){
  var msg = 'Added ids';
  for(var i = 0; i < added.length; i++) {
    msg += '\n' + added[i].id;
  }
  console.log(msg);
}
viewer.entities.collectionChanged.addEventListener(onChanged);

運行該示例時,您應(yīng)該在控制臺中看到大約65條消息,每次調(diào)用viewer.entities.add時都會看到一條消息。

當一次更新大量的實體時,將隊列更新結(jié)束后并在最后發(fā)送一個整體事件,這樣更具性能。這樣Cesium可以在一次通過中處理所需的變化。在示例末尾,在viewer.entities.add之前調(diào)用viewer.entities.suspendEvents,并調(diào)用viewer.entities.resumeEvents。當再次運行演示時,我們現(xiàn)在得到包含所有65個實體的單一事件。這些調(diào)用是引用計數(shù)的,因此可以嵌套多個掛起和恢復(fù)調(diào)用。

Picking 拾取

選擇(單擊選擇一個對象)是我們需要與基本API進行短暫交互的領(lǐng)域之一。使用scene.pickscene.drillpick檢索實體。

/**
 * Returns the top-most entity at the provided window coordinates
 * or undefined if no entity is at that location.
 *
 * @param {Cartesian2} windowPosition The window coordinates.
 * @returns {Entity} The picked entity or undefined.
 */
function pickEntity(viewer, windowPosition) {
  var picked = viewer.scene.pick(windowPosition);
  if (defined(picked)) {
    var id = Cesium.defaultValue(picked.id, picked.primitive.id);
    if (id instanceof Cesium.Entity) {
      return id;
    }
  }
  return undefined;
};

/**
 * Returns the list of entities at the provided window coordinates.
 * The entities are sorted front to back by their visual order.
 *
 * @param {Cartesian2} windowPosition The window coordinates.
 * @returns {Entity[]} The picked entities or undefined.
 */
function drillPickEntities(viewer, windowPosition) {
  var i;
  var entity;
  var picked;
  var pickedPrimitives = viewer.scene.drillPick(windowPosition);
  var length = pickedPrimitives.length;
  var result = [];
  var hash = {};

  for (i = 0; i < length; i++) {
    picked = pickedPrimitives[i];
    entity = Cesium.defaultValue(picked.id, picked.primitive.id);
    if (entity instanceof Cesium.Entity &&
        !Cesium.defined(hash[entity.id])) {
      result.push(entity);
      hash[entity.id] = true;
    }
  }
  return result;
};

Points, billboards, and labels(點、廣告牌和標簽)

通過設(shè)置positionpointlabel來創(chuàng)建圖形點或標簽。例如,在我們最喜歡的運動隊的主體育場放置一個點。

var viewer = new Cesium.Viewer('cesiumContainer');

var citizensBankPark = viewer.entities.add({
    name : 'Citizens Bank Park',
    position : Cesium.Cartesian3.fromDegrees(-75.166493, 39.9060534),
    point : {
        pixelSize : 5,
        color : Cesium.Color.RED,
        outlineColor : Cesium.Color.WHITE,
        outlineWidth : 2
    },
    label : {
        text : 'Citizens Bank Park',
        font : '14pt monospace',
        style: Cesium.LabelStyle.FILL_AND_OUTLINE,
        outlineWidth : 2,
        verticalOrigin : Cesium.VerticalOrigin.BOTTOM,
        pixelOffset : new Cesium.Cartesian2(0, -9)
    }
});

viewer.zoomTo(viewer.entities);

[圖片上傳失敗...(image-9c705e-1558490847491)]

默認情況下,標簽水平和垂直居中。由于標簽和點共享相同的位置,它們在屏幕上重疊。為避免這種情況,請指定標簽源Verticalorigin.BOTTOM并將像素偏移量設(shè)置為(0,-9)。
將該點替換為一個billboard,它是一個始終面向用戶的標記。

var citizensBankPark = viewer.entities.add({
  position : Cesium.Cartesian3.fromDegrees(-75.166493, 39.9060534),
  billboard : {
    image : '//cesiumjs.org/tutorials/Visualizing-Spatial-Data/images/Philadelphia_Phillies.png',
    width : 64,
    height : 64
  },
  label : {
    text : 'Citizens Bank Park',
    font : '14pt monospace',
    style: Cesium.LabelStyle.FILL_AND_OUTLINE,
    outlineWidth : 2,
    verticalOrigin : Cesium.VerticalOrigin.TOP,
    pixelOffset : new Cesium.Cartesian2(0, 32)
  }
});
image

有關(guān)更多自定義選項,請參見Sandcastle標簽廣告牌示例。

3D models (三維模型)

CesiumJS支持通過glTF(運行時asset format)創(chuàng)建3D模型。您可以在3D modelsSandcastle中找到示例模型。

將位置和URI設(shè)置為glTF 模型以創(chuàng)建模型實體。

var viewer = new Cesium.Viewer('cesiumContainer');
var entity = viewer.entities.add({
    position : Cesium.Cartesian3.fromDegrees(-123.0744619, 44.0503706),
    model : {
        uri : '../../../../Apps/SampleData/models/GroundVehicle/GroundVehicle.glb'
    }
});
viewer.trackedEntity = entity;
image

默認情況下,模型是垂直的,面向東。通過為Entity.Orientation屬性指定Quaternion來控制模型的方向。這將控制模型的heading、pitch和roll。

var viewer = new Cesium.Viewer('cesiumContainer');
var position = Cesium.Cartesian3.fromDegrees(-123.0744619, 44.0503706);
var heading = Cesium.Math.toRadians(45.0);
var pitch = Cesium.Math.toRadians(15.0);
var roll = Cesium.Math.toRadians(0.0);
var orientation = Cesium.Transforms.headingPitchRollQuaternion(position, new Cesium.HeadingPitchRoll(heading, pitch, roll));

var entity = viewer.entities.add({
    position : position,
    orientation : orientation,
    model : {
        uri : '../../../../Apps/SampleData/models/GroundVehicle/GroundVehicle.glb'
    }
});
viewer.trackedEntity = entity;

有關(guān)更高級的模型功能,請參見3D模型教程。如果你創(chuàng)建自己的模型,一定要看到我們關(guān)于glTF Tips for Artists提示的帖子。

The property system(屬性系統(tǒng))

我們?yōu)閷嶓w定義的所有值都存儲為property對象。例如,請參見懷俄明州大綱的值:

console.log(typeof wyoming.polygon.outline);

outlineConstantProperty的一個實例。本教程使用一種稱為隱式屬性轉(zhuǎn)換(implicit property conversion)的速記形式,它自動獲取原始值并在引擎蓋下創(chuàng)建相應(yīng)的Property。如果沒有這個速記,我們將不得不編寫一個更長版本的初始示例:

var wyoming = new Cesium.Entity();
wyoming.name = 'Wyoming';

var polygon = new Cesium.PolygonGraphics();
polygon.material = new Cesium.ColorMaterialProperty(Cesium.Color.RED.withAlpha(0.5));
polygon.outline = new Cesium.ConstantProperty(true);
polygon.outlineColor = new Cesium.ConstantProperty(Cesium.Color.BLACK);
wyoming.polygon = polygon;

viewer.entities.add(wyoming);

之所以使用屬性,是因為實體API不僅能夠表示常量值,而且能夠表示隨時間變化的值。請參閱Callback PropertyInterpolation Sandcastle示例,了解一些時間動態(tài)屬性。

資源

有關(guān)如何使用GeoJSONCZML設(shè)置樣式和創(chuàng)建實體的示例,請參閱Cesium Workshop Tutorial

Cesium中文網(wǎng)交流QQ群:807482793

Cesium中文網(wǎng):http://cesiumcn.org/ | 國內(nèi)快速訪問:http://cesium.coinidea.com/

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,622評論 6 544
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,716評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,746評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,991評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,706評論 6 413
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 56,036評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,029評論 3 450
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 43,203評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,725評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 41,451評論 3 361
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,677評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,161評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,857評論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,266評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,606評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,407評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,643評論 2 380