Cesium官方教程3 -- 空間數(shù)據(jù)可視化

原文地址:https://cesiumjs.org/tutorials/Visualizing-Spatial-Data/
這篇教程教你如何使用Cesium的Entity API去繪制空間數(shù)據(jù)厌殉,如點(diǎn),圖標(biāo)茄猫,文字標(biāo)注骚揍,折線吸占,模型,圖形和立體圖形。雖然這章不需要什么前提每辟,但是如果你對(duì)Cesium一無所知饺藤,最好從第一個(gè)教程開始包斑。

Entity API是什么?

Cesium豐富的空間數(shù)據(jù)可視化API分為兩部分:Primitive API 面向三維圖形開發(fā)者,更底層一些涕俗。Entity API 是數(shù)據(jù)驅(qū)動(dòng)更高級(jí)一些罗丰。

Primitive API的主要目的是為了完成(可視化)任務(wù)的最少的抽象需求。他要求我們以一個(gè)圖形開發(fā)者的方式去思考咽袜,并且使用了一些圖形學(xué)術(shù)語丸卷。它是為了最高效最靈活的實(shí)現(xiàn)可視化效果,忽略了API的一致性询刹。比如繪制三維模型和創(chuàng)建Billboard不同谜嫉,和多邊形繪制更是徹底不同。每種可視化都有自己鮮明的特色凹联。此外沐兰,他們每種都有自己的獨(dú)特的性能提升方式,也需要遵守不同的優(yōu)化原則蔽挠。雖然它很強(qiáng)大又很靈活住闯,但是大多數(shù)項(xiàng)目需要比Primitive API更高層次的抽象瓜浸。

Entity AP的主要目的是定義一組高級(jí)對(duì)象,它們把可視化和信息存儲(chǔ)到統(tǒng)一的數(shù)據(jù)結(jié)果中比原,這個(gè)對(duì)象叫Entity插佛。 它讓我們更加關(guān)注我們的數(shù)據(jù)展示而不是底層的可視化機(jī)制。它提供了很方便的創(chuàng)建復(fù)雜的量窘,與靜態(tài)數(shù)據(jù)相匹配的隨時(shí)間變化的可視化效果雇寇。Entity API實(shí)際內(nèi)部在使用Primitive API ,它的實(shí)現(xiàn)細(xì)節(jié)蚌铜,我們無需關(guān)心锨侯。經(jīng)過各種數(shù)據(jù)的測(cè)試,Entity API提供靈活的冬殃,高層次的可視化囚痴,同時(shí)暴露一些一致性的、容易去學(xué)習(xí)和使用的接口审葬。

第一個(gè) Entity

學(xué)習(xí)Entity API基本使用的最好方式就是去讀代碼深滚。簡(jiǎn)單其間,我們使用Sandcastle去創(chuàng)建 Hello World 示例耳璧。如果你已經(jīng)創(chuàng)建了本地的cesium項(xiàng)目成箫,那么使用你自己的項(xiàng)目。
假設(shè)旨枯,我們需要從經(jīng)緯度列表中創(chuàng)建美國(guó)懷俄明州(選擇懷俄明州Wyoming蹬昌,是因?yàn)樗倪吔缱銐蚝?jiǎn)單)的多邊形。把下面的代碼粘貼拷貝到Sandcastle中去:

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

var wyoming = viewer.entities.add({
  name : 'Wyoming',
  polygon : {
    hierarchy : Cesium.Cartesian3.fromDegreesArray([
                              -109.080842,45.002073,
                              -105.91517,45.002073,
                              -104.058488,44.996596,
                              -104.053011,43.002989,
                              -104.053011,41.003906,
                              -105.728954,40.998429,
                              -107.919731,41.003906,
                              -109.04798,40.998429,
                              -111.047063,40.998429,
                              -111.047063,42.000709,
                              -111.047063,44.476286,
                              -111.05254,45.002073]),
    height : 0,
    material : Cesium.Color.RED.withAlpha(0.5),
    outline : true,
    outlineColor : Cesium.Color.BLACK
  }
});

viewer.zoomTo(wyoming);

單機(jī)Run 按鈕(或者按下F8)就看到如下圖所示效果:


懷俄明州

第一個(gè) entity.懷俄明州從來沒有讓人如此興奮.
我們盡力使Cesium的代碼容易理解攀隔,上面的代碼不用解釋也應(yīng)該明白什么意思皂贩。首先創(chuàng)建Cesium程序的基礎(chǔ)對(duì)象 Viewer widget, 然后使用viewer.entities.add添加 Entity。傳給 add 方法的參數(shù)一個(gè)包含了初始化配置的js 對(duì)象. 返回值就是 entity 對(duì)象. 最后調(diào)用 viewer.zoomTo 定位到到這個(gè)entity昆汹。

Entity 的配置項(xiàng)里有大量的參數(shù)明刷,但是現(xiàn)在我們只是設(shè)置了 polygon 的填充面為半透明紅色,邊界線時(shí)黑色的满粗。最后把這個(gè)entity命名為“Wyoming”辈末。

面和體

學(xué)了基礎(chǔ)的添加多邊形知識(shí),多虧Entity API的一致性非常好映皆,我們結(jié)合Sandcastle 的示例挤聘,就很容易就創(chuàng)建各種圖形。下面是所有支持的面和體的圖形列表:

Box

六面體盒子entity.box

Ellipse

圓和橢圓entity.ellipse

Corridor

Corridor entity.corridor

Cylinder

圓柱和圓錐 entity.cylinder

Polygon

多邊形 entity.polygon

Polyline

折線 entity.polyline

Volume

Polyline Volumes entity.polylineVolume

Rectangle

矩形 entity.rectangle

Ellipsoid

球和橢球 entity.ellipsoid

Wall

entity.wall

材質(zhì)和邊線

無論他們的幾何體有什么不同捅彻,所有形狀和體都有一系列相同的屬性來控制它們的外觀组去。fill 為boolean類型,控制表面是否填充步淹。 outline 屬性控制是否有外邊界从隆。
當(dāng) fill=true诚撵,material屬性決定了用什么材質(zhì)填充表面。下個(gè)例子键闺,我們創(chuàng)建一個(gè)半透明橢圓寿烟。默認(rèn)fill=trueoutline=false艾杏,所以我們只需要設(shè)置material屬性韧衣。

var entity = viewer.entities.add({
  position: Cesium.Cartesian3.fromDegrees(-103.0, 40.0),
  ellipse : {
    semiMinorAxis : 250000.0,
    semiMajorAxis : 400000.0,
    material : Cesium.Color.BLUE.withAlpha(0.5)
  }
});
viewer.zoomTo(viewer.entities);
var ellipse = entity.ellipse;  
半透明橢圓

圖片材質(zhì)

直接設(shè)置一個(gè)圖片的url就可以了。

ellipse.material = '//cesiumjs.org/tutorials/images/cats.jpg';

圖片材質(zhì)

上面兩個(gè)示例李, 當(dāng)設(shè)置顏色或者url之后Cesium會(huì)自動(dòng)創(chuàng)建 ColorMaterialProperty 或者ImageMaterialProperty對(duì)象购桑。 對(duì)于更復(fù)雜的材質(zhì), 需要手動(dòng)創(chuàng)建 MaterialProperty對(duì)象。 當(dāng)前, Entity 面和體支持 顏色(colors),紋理圖片( images),棋盤 (checkerboard), 條紋(stripe), 網(wǎng)格(grid)等材質(zhì).

網(wǎng)格材質(zhì)

ellipse.material = new Cesium.CheckerboardMaterialProperty({
  evenColor : Cesium.Color.WHITE,
  oddColor : Cesium.Color.BLACK,
  repeat : new Cesium.Cartesian2(4, 4)
});
網(wǎng)格材質(zhì)

條紋材質(zhì)

ellipse.material = new Cesium.StripeMaterialProperty({
  evenColor : Cesium.Color.WHITE,
  oddColor : Cesium.Color.BLACK,
  repeat : 32
});

條紋材質(zhì)

網(wǎng)格材質(zhì)

ellipse.material = new Cesium.GridMaterialProperty({
  color : Cesium.Color.YELLOW,
  cellAlpha : 0.2,
  lineCount : new Cesium.Cartesian2(8, 8),
  lineThickness : new Cesium.Cartesian2(2.0, 2.0)
});

網(wǎng)格材質(zhì)

邊線

fill屬性不太一樣氏淑,outline沒有對(duì)應(yīng)的材質(zhì)配置勃蜘,而是用兩個(gè)獨(dú)立的屬性outlineColoroutlineWidth
注意outlineWidth屬性僅僅在非windows系統(tǒng)上有效假残,比如Android, iOS, Linux, 和OS X缭贡。Windows系統(tǒng)上邊線寬度永遠(yuǎn)為1。主要是因?yàn)槿笾髁鳛g覽器引擎在windows平臺(tái)上實(shí)現(xiàn)webgl上的技術(shù)限制辉懒。

ellipse.fill = false;
ellipse.outline = true;
ellipse.outlineColor = Cesium.Color.YELLOW;
ellipse.outlineWidth = 2.0;

邊線

折線

折線是個(gè)特例阳惹,他沒有填充或者邊線屬性。除了顏色它有專門的材質(zhì)屬性眶俩。由于這種特殊材質(zhì)莹汤,折線寬度和折線的邊線寬度,在所有系統(tǒng)都有效颠印。

var entity = viewer.entities.add({
    polyline : {
        positions : Cesium.Cartesian3.fromDegreesArray([-77, 35,
                                                        -77.1, 35]),
    width : 5,
    material : Cesium.Color.RED
}});
viewer.zoomTo(viewer.entities);
var polyline = entity.polyline // For upcoming examples
折線

折線邊線

polyline.material = new Cesium.PolylineOutlineMaterialProperty({
    color : Cesium.Color.ORANGE,
    outlineWidth : 3,
    outlineColor : Cesium.Color.BLACK
});

折線的邊線

折線輝光

polyline.material = new Cesium.PolylineGlowMaterialProperty({
    glowPower : 0.2,
    color : Cesium.Color.BLUE
});

折線輝光

高度和垂直擠壓(Extrusions)

所有的面形狀都是平鋪在地球上纲岭,當(dāng)前 圓(circles)、橢圓(ellipses)线罕、多邊形(polygons)止潮、矩形(rectangles)可以有一個(gè)高程屬性 或者 垂直擠壓變成體。這兩種情況種钞楼,這些面或者體仍然會(huì)貼合地球曲率喇闸。
上面我們列出的所有圖形,都是只需要在圖形對(duì)象(graphics )上設(shè)置一個(gè)高度屬性即可询件。這里順便說明下燃乍,除非在函數(shù)上明確說明,否則Cesium總是使用米雳殊、弧度橘沥、秒做為標(biāo)準(zhǔn)單位。如 Cartesian3.fromDegrees.
下面這行代碼把多邊形放到了 250,000米高空夯秃。

wyoming.polygon.height = 250000;
250,000 米高空的懷俄明

把圖形擠壓為體座咆,也非常簡(jiǎn)單痢艺。僅僅需要設(shè)置 extrudedHeight 屬性。將會(huì)創(chuàng)建一個(gè)在heightextrudedHeight之間的體塊介陶。如果 height 沒有定義, 體塊從 0高程開始堤舒。下面代碼創(chuàng)建一個(gè)從200,000米到 250,000米的體 。也就是說這個(gè)體的高度是50000米哺呜。

wyoming.polygon.height = 200000;
wyoming.polygon.extrudedHeight = 250000;
垂直擠壓

對(duì)多邊形變成體也非常容易

Viewer中的Entity 元素(feature)

在開始其他可視化效果學(xué)習(xí)之前舌缤,讓我們先看看 Viewer 中提供的和Entity相關(guān)的函數(shù)。

選中和描述

除非明確禁用某残,否則點(diǎn)擊Entity將在它的位置會(huì)顯示 SelectionIndicator 控件国撵,并且在 InfoBox 控件里顯示它的描述信息〔J回想我們最開始的示例介牙,我們僅僅為 wyoming entity設(shè)置了name屬性,它顯示在 InfoBox標(biāo)題欄, 也可以通過 Entity.description 設(shè)置一段HTML當(dāng)作infobox的內(nèi)容澳厢。 把下面的代碼追加到上面的示例里:

wyoming.description = '\
<img\
  width="50%"\
  style="float:left; margin: 0 1em 1em 0;"\
  src="http://cesiumjs.org/tutorials/Visualizing-Spatial-Data/images/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 62,448 in 2013.\
</p>\
<p>\
  Source: \
  <a style="color: WHITE"\
    target="_blank"\
    >Wikpedia</a>\
</p>';

設(shè)置Entity描述信息

很多項(xiàng)目都是從服務(wù)端返回描述信息环础,而不是上面這種硬編碼,不過這種方法是可行的剩拢。
默認(rèn)线得,在InfoBox 里所有的HTML是沙盒模式。這個(gè)防止外部的數(shù)據(jù)注入惡意的代碼徐伐。如果你需要在描述信息里運(yùn)行js腳本或者瀏覽器插件贯钩,可以通過viewer.infoBox.frame屬性來訪問這個(gè)iframe。更多關(guān)于iframe的沙盒模式呵晨,請(qǐng)參考這篇文章 魏保。

相機(jī)控制

就像第一個(gè)例子中,我們使用 zoomTo 命令去顯示一個(gè)特定的entity摸屠。雙擊Entity或者點(diǎn)擊 InfoBox左上角按鈕谓罗,也能達(dá)到同樣效果. 還有一個(gè) flyTo 方法,它不是立即定位過去季二,而是執(zhí)行一個(gè)相機(jī)動(dòng)畫漸變過去檩咱。這些方法除了應(yīng)用在單獨(dú)一個(gè)entity上,也可以作用在 EntityCollection對(duì)象上或者一個(gè)普通的js entity數(shù)組,胯舷。
默認(rèn)刻蚯,這些方法會(huì)自動(dòng)計(jì)算一個(gè)視圖,確保所有所有傳到方法里的entity都可見桑嘶,相機(jī)朝向正北炊汹,以45°傾斜俯視√佣ィ可以提供一個(gè)自定義的heading, pitch, and range.來修改這個(gè)朝向讨便。下面代碼執(zhí)行后相機(jī)會(huì)從東方向下傾斜30°角去看懷俄明的多邊形充甚。因?yàn)槲覀儧]有設(shè)定range參數(shù),那么這個(gè)參數(shù)還是按照默認(rèn)計(jì)算的結(jié)果霸褒。

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

自定義視角

zoomToflyTo 都是異步函數(shù), 也就是說當(dāng)函數(shù)return的時(shí)候伴找,并不能保證執(zhí)行完畢了。一般flyto會(huì)在很多個(gè)動(dòng)畫幀里都運(yùn)算废菱。這些函數(shù)都返回一個(gè) Promises 技矮,我們可以把飛行或者縮放完成后需要制定的代碼放到 then函數(shù)里。我們把以下代碼片段里換成 zoomTo 殊轴,并且在飛行完畢后會(huì)同時(shí)選中這個(gè)entity衰倦。

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

這里回調(diào)函數(shù)里的result參數(shù),true表示飛行正常完成旁理,false 飛行被打斷 或者 用戶開啟了另一個(gè)飛行定位函數(shù)耿币,再或者目標(biāo)對(duì)象無法被可視化也就沒辦法去定位了。
有時(shí)候韧拒,尤其是展示一個(gè)隨時(shí)間變化的數(shù)據(jù),我們希望相機(jī)能跟隨這個(gè)entity十性。這個(gè)通過設(shè)置 viewer.trackedEntity就很容易實(shí)現(xiàn)叛溢。跟隨一個(gè)entity要求position屬性必須存在。還是通過我們的Wyoming 多邊形entity來測(cè)試這個(gè)模式劲适,我們給它增加個(gè)position屬性楷掉,代碼如下:

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

viewer.trackedEntity 設(shè)置為undefined 或者點(diǎn)擊 InfoBox的左上的取消按鈕都可以停止跟隨模式。 調(diào)用zoomTo 或者 flyTo 也會(huì)取消跟隨模式霞势,并且 把 viewer.trackedEntity 設(shè)置為 undefined烹植。
大部分情況下,在 Viewer 中定義的和entity相關(guān)的相機(jī)函數(shù)足夠使用了愕贡。但是如果你想在項(xiàng)目更多的自定義相機(jī)視圖方式草雕,請(qǐng)查看 相機(jī)教程

管理Entity集合

EntityCollection類是一個(gè)Entity數(shù)組集合固以,用來它管理和控制一組entity非常方便墩虹。我們已經(jīng)見過它的一個(gè)實(shí)例 viewer.entities 屬性。EntityCollection 提供了基本的數(shù)組方法 add, remove, 和 removeAll;同時(shí)還有下面我們要討論的一些特有方法或者屬性憨琳。
很多項(xiàng)目的數(shù)據(jù)實(shí)際都是存在服務(wù)端的诫钓,只有客戶端需要的時(shí)候才會(huì)加載。有時(shí)候需要更改一個(gè)我們已經(jīng)創(chuàng)建的entity篙螟。所有entity對(duì)象都有一個(gè)獨(dú)一無二的 id 屬性菌湃,這種情況情況下就非常有用。前面的示例里遍略,我們并沒有指定這個(gè)id惧所,Cesium會(huì)自動(dòng)生成一個(gè) GUID 類似182bdba4-2b3e-47ae-bf0b-83f6fde285fd 填充到id屬性里骤坐。服務(wù)端的數(shù)據(jù)一般都有自己主鍵id屬性,所以可以在enity創(chuàng)建的時(shí)候指定這個(gè)id纯路。

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

隨后或油,可以通過 getById來獲取Entity對(duì)象。如果沒有找到對(duì)應(yīng)的id驰唬,那么該方法返回 undefined顶岸。

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

另一個(gè)常見的應(yīng)用,是如果id不存在就新建叫编,如果id存在就更新辖佣。 getOrCreateEntity 總會(huì)返回以傳入的參數(shù)為id的對(duì)象實(shí)例, 如果id不存在搓逾,那么會(huì)新建一個(gè)卷谈,并且增加到entity集合里,然后返回霞篡。

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

最后世蔗,簡(jiǎn)單的通過 add就可以新建一個(gè)Entity實(shí)例。這種情況下朗兵,add函數(shù)會(huì)檢測(cè)如果傳入了一個(gè)已經(jīng)存在的id污淋,那么會(huì)報(bào)異常。

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

EntityCollection 最強(qiáng)大的功能其實(shí)是collectionChanged Event余掖,我們用它來接收集合里entity被添加寸爆、刪除甚至更新的通知。當(dāng)項(xiàng)目里的用戶界面或者某個(gè)功能需要監(jiān)控集合里的對(duì)象改變的時(shí)候盐欺,這個(gè)功能非常有用赁豆。

為了驗(yàn)證這點(diǎn),可以試下Sandcastle的實(shí)例 Geometry 示例 冗美。把下面的代碼拷貝到緊跟viewer 創(chuàng)建的地方魔种。

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);

當(dāng)運(yùn)行示例的時(shí)候,控制臺(tái)輸出了65條消息墩衙。每調(diào)用一次 viewer.entities.add就會(huì)有一條消息 ( removedchanged在這里沒有提示务嫡,因?yàn)槲覀冞@個(gè)項(xiàng)目里只有add)。為了更新可視化效果漆改,Cesium內(nèi)部實(shí)際也訂閱了這個(gè)事件心铃。當(dāng)一次性更新的數(shù)量過多的時(shí)候,先一個(gè)個(gè)更新挫剑,最后統(tǒng)一發(fā)消息效率更高去扣。因?yàn)镃esium只處理了一遍變化消息,所以這個(gè)對(duì)性能有提升。 在修改之前愉棱,我們先調(diào)用 viewer.entities.suspendEvents唆铐,修改完之后再調(diào)用 viewer.entities.resumeEvents.

我們?cè)囅逻@個(gè)。在第一次調(diào)用 viewer.entities.add 前添加一個(gè)suspend調(diào)用奔滑,在最后調(diào)用一下resume 艾岂。再次運(yùn)行下程序,我們現(xiàn)在只收到一條消息朋其,但是里面包含了65條entity添加記錄王浴。 這個(gè)函數(shù)調(diào)用有內(nèi)部計(jì)數(shù),所以多重嵌入調(diào)用suspend 和resume沒有任何問題梅猿∶ダ保可是,如果忘了調(diào)用resume袱蚓,那么在處理完之后會(huì)獲取不了任何信息钞啸。因?yàn)閞esume只有在對(duì)應(yīng)層次的suspend下才會(huì)發(fā)出消息(也就是suspend和resume必須是匹配的)。

拾取

拾取喇潘,也就是返回特定屏幕坐標(biāo)(通常是鼠標(biāo)位置)的對(duì)象体斩,這也是這部分唯一需要和Primitive API打交道的功能。這部分未來在講Cesium的Entity拾取技術(shù)功能的時(shí)候會(huì)再次討論颖低。 現(xiàn)在我們使用一些低層次的方法 scene.pickscene.drillPick 硕勿。下面代碼是拾取部分的一個(gè)基本實(shí)現(xiàn),基本上可以直接在項(xiàng)目里使用 枫甲。

/**
 * 返回對(duì)應(yīng)窗口位置最上面一個(gè)Entity 如果該位置沒有對(duì)象那么返回undefined
 * @param {Cartesian2} windowPosition 窗口坐標(biāo)
 * @returns {Entity} 返回值
 */
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;
};

/**
 *返回對(duì)應(yīng)窗口位置所有Entity的列表 如果該位置沒有對(duì)象那么返回undefined
 * 返回值按可視化順序從前到后存儲(chǔ)在數(shù)組里
 *
 * @param {Cartesian2} windowPosition 窗口位置
 * @returns {Entity[]}  
 */
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;
};

來解釋下。 場(chǎng)景的拾取函數(shù)返回的是圖元信息而不是entity對(duì)象扼褪,但是Entity API的結(jié)構(gòu)限定每一個(gè)圖元會(huì)對(duì)應(yīng)到一個(gè)entity實(shí)體上想幻,通過他們的 id 屬性來區(qū)分。所以我們只需要檢測(cè)拾取的對(duì)象id是否是一個(gè) Entity. 這些函數(shù)是不重要的(trivial)话浇,它還沒有被當(dāng)作Cesium的正式部分脏毯,我們有一些更加穩(wěn)定的函數(shù)計(jì)劃(more robust functionality planned) 。

點(diǎn)(Points),公告牌( Billboards), 標(biāo)注(Labels)

別考慮面和體了幔崖,我們來學(xué)下在Cesium上如何展示POI點(diǎn)食店。 創(chuàng)建一個(gè)點(diǎn)或者標(biāo)注非常簡(jiǎn)單,只需要設(shè)置entity 的 position 屬性赏寇,以及point 或者label 可視化對(duì)象吉嫩。比如,我想在我最喜歡的球隊(duì)主場(chǎng)放一個(gè)點(diǎn)嗅定。

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);

點(diǎn)和標(biāo)注

上面的示例里自娩,我們精確指定了公告牌的寬度和高度,但其實(shí)是不需要的渠退,如果沒有指定忙迁,那么將使用圖片的高度和寬度脐彩。
標(biāo)注和公告板有大量的選項(xiàng),我們就不深入講解了姊扔。具體可以查看Sandcastle里的對(duì)應(yīng)示例: 標(biāo)注, 公告板惠奸。

三維模型

Cesium通過 glTF格式支持三維模型,glTF是 WebGL, OpenGL ES, and OpenGL的實(shí)時(shí)載入模型(the runtime asset format)恰梢。Cesium包含了一些可以使用的glTF模型 : 帶螺旋槳?jiǎng)赢嫷娘w機(jī)佛南,帶輪子動(dòng)畫的汽車模型,帶行走動(dòng)畫的人物模型删豺。在Sandcastle 示例里可以看到他們 三維模型 共虑。
加載三維模型和前面其他的可視數(shù)據(jù)區(qū)別不大。只需要entity帶position屬性和一個(gè)指向glTF模型資源的uri路徑呀页。

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;

卡車模型

你可以配置一個(gè) scale 屬性妈拌,它將等比例縮放模型。也可以配置一個(gè) minimumPixelSize 屬性蓬蝶,它保證距離模型很遠(yuǎn)的時(shí)候尘分,模型不會(huì)小于設(shè)定的大小。
默認(rèn)丸氛,模型向右朝向東方培愁。可以通過 Entity.orientation 的屬性設(shè)定一個(gè) 四元數(shù)Quaternion缓窜。這個(gè)比前面只用位置的示例更麻煩一些定续,讓我們?cè)O(shè)定一下模型的 heading, pitch, roll。把下面代碼拷貝到 Sandcastle禾锤,修改一下值 可以查看具體的效果私股。

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;

因此模型需要轉(zhuǎn)為glTF格式才能在Cesium中使用。我們提供了一個(gè) 在線的轉(zhuǎn)換工具 恩掷,你可以上傳COLLADA (dae)模型就會(huì)下載到glTF格式的倡鲸。
當(dāng)前Entity API還不支持模型的高級(jí)使用場(chǎng)景,比如模型節(jié)點(diǎn)的拾取或者動(dòng)畫控制黄娘,不過可以使用Primitive API 實(shí)現(xiàn)峭状。我們有一個(gè)單獨(dú)的教程來實(shí)現(xiàn)這些功能 三維模型高級(jí)教程 。未來我們肯定會(huì)增強(qiáng) Entity API包含這些功能逼争。這個(gè)高級(jí)教程包含了如何在Cesium下調(diào)試模型顯示的異常效果优床,所以一定要去學(xué)習(xí)它。如果你設(shè)計(jì)了自己的模型誓焦,一定要去看看我們的 建模人員 glTF 貼士.

屬性系統(tǒng)

到目前羔巢,我們都是設(shè)置了entity的圖形對(duì)象屬性,還沒有實(shí)際讀取過屬性。事實(shí)上竿秆,我們可能會(huì)對(duì)返回的結(jié)果感覺驚訝启摄。回想我們第一個(gè)多邊形示例里幽钢,我們把outline屬性設(shè)置為 true 歉备。直覺告訴我們,如果我們用日志輸出(console.log)獲取wyoming.polygon.outline的類型匪燕,將輸出 boolean蕾羊。

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

可是上述代碼的輸出實(shí)際是 object。因?yàn)?outline 不是一個(gè)簡(jiǎn)單的布爾類型帽驯,而是一個(gè)ConstantProperty類的實(shí)例龟再。實(shí)時(shí)上,這個(gè)教程整個(gè)使用的一種叫隱形屬性轉(zhuǎn)換的簡(jiǎn)略形式來設(shè)置屬性尼变,它會(huì)自動(dòng)的使用原始值創(chuàng)建一個(gè)對(duì)應(yīng)的 ConstantProperty 類實(shí)例利凑。如果沒有這種簡(jiǎn)略形式,我們就不得不去寫一個(gè)更長(zhǎng)的初始化示例代碼:

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);

為什么 屬性是這種形式嫌术?原因很簡(jiǎn)單哀澈,整個(gè)Entity API的屬性設(shè)計(jì)是不僅僅考慮是一個(gè)常量值,而需要設(shè)置一些隨時(shí)間變換的值度气。
所有的屬性類實(shí)現(xiàn) Property 接口, Cesium中定義了很多種屬性類割按。本教程的第二部分將重點(diǎn)關(guān)注屬性系統(tǒng),使用它去創(chuàng)建一個(gè)時(shí)間變化的動(dòng)態(tài)可視化效果磷籍。 現(xiàn)在适荣,我們唯一需要知道的是:為了讀取屬性的值,我們需要調(diào)用 getValue函數(shù)院领。所以為了獲得多邊形的outline屬性束凑,應(yīng)該寫類似下面的代碼,時(shí)間參數(shù)傳當(dāng)前場(chǎng)景時(shí)間即可栅盲。

console.log(wyoming.polygon.outline.getValue(viewer.clock.currentTime));

嚴(yán)格來說,如果我們明確知道正在讀取一個(gè) ConstantProperty的值废恋,那么可以不需要傳遞時(shí)間參數(shù)谈秫。但是明確指定時(shí)間參數(shù)是個(gè)慣例。

接下來干什么

我們勉強(qiáng)學(xué)習(xí)了Cesium加載空間數(shù)據(jù)可視化的一點(diǎn)皮毛鱼鼓,但是我們已經(jīng)解鎖了一個(gè)巨大的可能性拟烫。等待這個(gè)教程第二部分的同時(shí),或許可以學(xué)習(xí)下Cesium對(duì) 影像圖層 或者 地形和水面的支持迄本。也可以看下所有教程列表 看看有沒有感興趣的硕淑。

中國(guó)最專業(yè)的Cesium開發(fā)者社區(qū)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子置媳,更是在濱河造成了極大的恐慌于樟,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,968評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件拇囊,死亡現(xiàn)場(chǎng)離奇詭異迂曲,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)寥袭,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門路捧,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人传黄,你說我怎么就攤上這事杰扫。” “怎么了膘掰?”我有些...
    開封第一講書人閱讀 153,220評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵章姓,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我炭序,道長(zhǎng)啤覆,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,416評(píng)論 1 279
  • 正文 為了忘掉前任惭聂,我火速辦了婚禮窗声,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘辜纲。我一直安慰自己笨觅,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,425評(píng)論 5 374
  • 文/花漫 我一把揭開白布耕腾。 她就那樣靜靜地躺著见剩,像睡著了一般。 火紅的嫁衣襯著肌膚如雪扫俺。 梳的紋絲不亂的頭發(fā)上苍苞,一...
    開封第一講書人閱讀 49,144評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音狼纬,去河邊找鬼羹呵。 笑死,一個(gè)胖子當(dāng)著我的面吹牛疗琉,可吹牛的內(nèi)容都是我干的冈欢。 我是一名探鬼主播,決...
    沈念sama閱讀 38,432評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼盈简,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼凑耻!你這毒婦竟也來了太示?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,088評(píng)論 0 261
  • 序言:老撾萬榮一對(duì)情侶失蹤香浩,失蹤者是張志新(化名)和其女友劉穎类缤,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體弃衍,經(jīng)...
    沈念sama閱讀 43,586評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡呀非,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,028評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了镜盯。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片岸裙。...
    茶點(diǎn)故事閱讀 38,137評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡崩哩,死狀恐怖泉褐,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情萍程,我是刑警寧澤艺糜,帶...
    沈念sama閱讀 33,783評(píng)論 4 324
  • 正文 年R本政府宣布剧董,位于F島的核電站,受9級(jí)特大地震影響破停,放射性物質(zhì)發(fā)生泄漏翅楼。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,343評(píng)論 3 307
  • 文/蒙蒙 一真慢、第九天 我趴在偏房一處隱蔽的房頂上張望毅臊。 院中可真熱鬧,春花似錦黑界、人聲如沸管嬉。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蚯撩。三九已至,卻和暖如春烛占,著一層夾襖步出監(jiān)牢的瞬間胎挎,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評(píng)論 1 262
  • 我被黑心中介騙來泰國(guó)打工忆家, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留犹菇,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,595評(píng)論 2 355
  • 正文 我出身青樓弦赖,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親浦辨。 傳聞我的和親對(duì)象是個(gè)殘疾皇子蹬竖,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,901評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容