原文地址: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)建各種圖形。下面是所有支持的面和體的圖形列表:
六面體盒子entity.box
圓和橢圓entity.ellipse
Corridor entity.corridor
圓柱和圓錐 entity.cylinder
多邊形 entity.polygon
折線 entity.polyline
Polyline Volumes entity.polylineVolume
矩形 entity.rectangle
球和橢球 entity.ellipsoid
墻 entity.wall
材質(zhì)和邊線
無論他們的幾何體有什么不同捅彻,所有形狀和體都有一系列相同的屬性來控制它們的外觀组去。fill
為boolean類型,控制表面是否填充步淹。 outline
屬性控制是否有外邊界从隆。
當(dāng) fill
=true
诚撵,material
屬性決定了用什么材質(zhì)填充表面。下個(gè)例子键闺,我們創(chuàng)建一個(gè)半透明橢圓寿烟。默認(rèn)fill
=true
, outline
=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';
上面兩個(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)
});
條紋材質(zhì)
ellipse.material = new Cesium.StripeMaterialProperty({
evenColor : Cesium.Color.WHITE,
oddColor : Cesium.Color.BLACK,
repeat : 32
});
網(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)
});
邊線
和 fill
屬性不太一樣氏淑,outline
沒有對(duì)應(yīng)的材質(zhì)配置勃蜘,而是用兩個(gè)獨(dú)立的屬性outlineColor
和outlineWidth
。
注意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;
把圖形擠壓為體座咆,也非常簡(jiǎn)單痢艺。僅僅需要設(shè)置 extrudedHeight
屬性。將會(huì)創(chuàng)建一個(gè)在height
和extrudedHeight
之間的體塊介陶。如果 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>';
很多項(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));
zoomTo 和flyTo 都是異步函數(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ì)有一條消息 ( removed
和 changed
在這里沒有提示务嫡,因?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.pick 和scene.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);
上面的示例里自娩,我們精確指定了公告牌的寬度和高度,但其實(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ì) 影像圖層 或者 地形和水面的支持迄本。也可以看下所有教程列表 看看有沒有感興趣的硕淑。