Cesium中级教程4 - 空间数据可视化(二)

Cesium中文网:http://cesiumcn.org/ | 国内快速访问:http://cesium.coinidea.com/

Viewer中的Entity功能

让我们看看Viewer为操作entities提供出来的功能函数。

选中和描述

点击Viewer中的entity将在entity的位置上呈现SelectionIndicator控件,提供一个InfoBox用于呈现更多的信息。我们可以设置name,来定义InfoBox的标题。我们也以HTML样式来提供Entity.description的属性。

wyoming.name = 'wyoming';
wyoming.description = '\
<img\
  width="50%"\
  style="float:left; margin: 0 1em 1em 0;"\
  src="//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"\
    href="http://en.wikipedia.org/wiki/Wyoming">Wikpedia</a>\
</p>';
image

InfoBox中展示的所有HTML是沙盒式的。这组织了外部数据源带有恶意的注入到Cesium的应用程序中。为了在描述中运行JavaScript或浏览器插件,访问沙盒中的iframe通过viewer.infoBox.frame属性。参考该文 可以获得更多的信息用于控制iframe中的沙盒。

Camera控制

使用iewer.zoomto命令查看特定Entity。还有一个viewer.flyto方法,用于对Entity执行动画Camera飞行。这两种方法都可以传递给EntityEntityCollectionDataSource或实体数组。

任何一种方法都会计算所有提供的实体的视图。默认情况下,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都是异步函数;也就是说,它们不能保证在返回之前完成。例如,飞行到Entity会在许多动画帧后发生。这两个功能都返回Promises,可用于计划飞行或缩放完成后要执行的功能。用下面的代码片段替换示例中的zoomTo。这架飞机飞往怀俄明州,并在飞行结束后选中它。

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

如果航班飞行成功完成,则传递给回调函数的结果参数将为true;如果航班被取消,则结果参数将为false,即,在此航班完成之前,用户启动了另一个航班或缩放;或者,由于目标没有相应的可视化效果,即没有可缩放的对象。

有时,特别是在处理时间动态数据时,我们希望Camera聚焦跟随一个entity而不是地球的中心。可以通过设置viewer.trackedEntity完成。跟踪实体需要设置position

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

停止跟踪需要设置viewer.trackedEntityundefined或远离entity双击屏幕即可。调用zoomToflyTo也可以取消跟踪。

管理Entities

EntityCollection是用于管理和监视一组实体的关联数组。viewer.entitiesEntityCollectionEntityCollection包括用于管理实体的方法,如addremoveremoveAll

有时我们需要更新我们以前创建的实体。所有实体实例都有一个唯一的id,可用于从集合中检索实体。我们可以为实体指定一个ID,否则将自动生成一个ID。

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

使用getByiId检索实体。如果不存在具有提供的ID的实体,则返回undefined

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

要获取实体或创建新实体(如果不存在),请使用getOrCreateEntity

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

手动创建新实体,然后使用add将其添加到集合中。如果集合中已存在具有相id的实体,则此方法将抛出异常。

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

EntityCollection的功能使用CollectionChanged事件发光。当在集合中添加、删除或更新实体时,会通知监听器。

使用Sandcastle中的[Geometry Showcase]
(https://cesiumjs.org/Cesium/Build/Apps/Sandcastle/index.html?src=Geometry%20and%20Appearances.html&label=Showcases) 示例。在创建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);

运行该示例时,您应该在控制台中看到大约65条消息,每次调用viewer.entities.add时都会看到一条消息。

当一次更新大量的实体时,将队列更新结束后并在最后发送一个整体事件,这样更具性能。这样Cesium可以在一次通过中处理所需的变化。在示例末尾,在viewer.entities.add之前调用viewer.entities.suspendEvents,并调用viewer.entities.resumeEvents。当再次运行演示时,我们现在得到包含所有65个实体的单一事件。这些调用是引用计数的,因此可以嵌套多个挂起和恢复调用。

Picking 拾取

选择(单击选择一个对象)是我们需要与基本API进行短暂交互的领域之一。使用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(点、广告牌和标签)

通过设置positionpointlabel来创建图形点或标签。例如,在我们最喜欢的运动队的主体育场放置一个点。

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并将像素偏移量设置为(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

有关更多自定义选项,请参见Sandcastle标签广告牌示例。

3D models (三维模型)

CesiumJS支持通过glTF(运行时asset format)创建3D模型。您可以在3D modelsSandcastle中找到示例模型。

将位置和URI设置为glTF 模型以创建模型实体。

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;

有关更高级的模型功能,请参见3D模型教程。如果你创建自己的模型,一定要看到我们关于glTF Tips for Artists提示的帖子。

The property system(属性系统)

我们为实体定义的所有值都存储为property对象。例如,请参见怀俄明州大纲的值:

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

outlineConstantProperty的一个实例。本教程使用一种称为隐式属性转换(implicit property conversion)的速记形式,它自动获取原始值并在引擎盖下创建相应的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示例,了解一些时间动态属性。

资源

有关如何使用GeoJSONCZML设置样式和创建实体的示例,请参阅Cesium Workshop Tutorial

Cesium中文网交流QQ群:807482793

Cesium中文网:http://cesiumcn.org/ | 国内快速访问:http://cesium.coinidea.com/

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343