什么是entities
CesiumJS具有丰富的空间数据API,可分为两类:面向图形开发人员的低级Primitive API,以及用于数据驱动可视化的高级Entity API。
entitiesAPI公开了一组一致设计的高级对象,这些对象将相关的可视化和信息聚合到一个统一的数据结构中,我们称之为实体。它让我们专注于数据的呈现,而不是担心可视化的潜在机制。它还以一种与静态数据自然结合的方式,为轻松构建复杂的时间动态可视化提供了结构。虽然实体API实际上在幕后使用原始API,但这是我们(几乎)永远不用关心的实现细节。通过对我们提供的数据应用各种启发式,实体API能够提供灵活、高性能的可视化,同时公开一致、易于学习和易于使用的界面。
创建第一个实体
const viewer = new window.Cesium.Viewer("cesiumContainer");
const wyoming = viewer.entities.add({
// 多边形
polygon: {
// 将经纬度数组转换为笛卡尔坐标数组
hierarchy: window.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: window.Cesium.Color.RED.withAlpha(0.5),
// 轮廓
outline: true,
outlineColor: window.Cesium.Color.BLACK,
},
});
//将场景缩放到适合所有实体的范围。它会根据场景中所有实体的位置和尺寸自动调整相机的位置和方向
viewer.zoomTo(wyoming);
形状和体积
- 盒子(entity.box)
- 圆和椭圆(entity.ellipse)
- 通道(entity.corridor)
- 圆柱体和圆锥体(entity.cylinder)
- 多边形(entity.polygon)
- 折线(entity.polyline)
- 折线卷(entity.polylineVolume)
- 矩形(entity.rectangle)
- 球体和椭圆体(entity.ellipsoid)
- 墙(entity.wall)
材料和轮廓
所有形状和体积都有一组共同的属性来控制它们的外观。该 fill 属性指定几何图形是否被填充,该 outline 属性指定几何图形是否被勾勒。
我们设置一般针对material属性
const 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);
我们还可以指定图像的 url 而不是颜色
ellipse.material = "/docs/tutorials/creating-entities/images/cats.jpg";
还有棋盘,条纹,网格,轮廓线,折线,折线轮廓,折线辉光等
参考地址
高度和挤压(拉伸)
包括走廊、椭圆、多边形和矩形在内的曲面形状可以放置在高度或拉伸到体积中。在这两种情况下,形状或体积仍将符合WGS84椭球体的曲率。
// 将多边形提升到地球上方 250,000 米。
wyoming.polygon.height = 250000;
讲图形挤压(拉伸)成体积,需要设置extrudedHeight属性。体积将在高度和拉伸高度之间创建。如果未定义高度,则体积从0开始。
// 创建一个从 200,000 米开始并延伸到 250,000 米的体积
wyoming.polygon.height = 200000;
wyoming.polygon.extrudedHeight = 250000;
选择与说明
单击查看器中的某个实体将在该实体的位置显示SelectionIndicator小部件,并显示InfoBox以提供更多信息。我们可以设置一个名称,该名称决定InfoBox的标题。我们还可以提供HTML作为Entity.description属性。
wyoming.name = "wyoming";
wyoming.description =
'\
<img\
width="50%"\
style="float:left; margin: 0 1em 1em 0;"\
src="/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>';
相机控制
使用viewer.zoomTo命令可以查看特定实体。还有一个viewer.flyTo方法,用于执行到实体的动画摄影机飞行。这两个方法都可以传递给Entity、EntityCollection、DataSource或实体数组。
任何一种方法都会计算所有提供实体的视图。默认情况下,摄影机指向北方,并从45度角向下观看。通过传入HeadingPitchRange来自定义此选项。
const heading = Cesium.Math.toRadians(90);
const pitch = Cesium.Math.toRadians(-30);
viewer.zoomTo(wyoming, new Cesium.HeadingPitchRange(heading, pitch));
zoomTo和flyTo都是异步函数;也就是说,他们不能保证在返回之前完成。例如,飞行到一个实体发生在许多动画帧上。这两个函数都返回Promises,可用于安排飞行或缩放完成后执行的函数。将我们示例中的zoomTo替换为下面的片段。这架飞机飞往怀俄明州,并在飞行完成后选择它。
const result = await viewer.flyTo(wyoming);
if (result) {
viewer.selectedEntity = wyoming;
}
通过将viewer.trackedEntity设置为undefined或双击离开实体来停止跟踪。调用zoomTo或flyTo也将取消跟踪。
管理实体
EntityCollection(实体收集)是一个数组,用来管理和监视一组实体。
viewer.entities 是一个 EntityCollection。 包括用于管理实体的EntityCollection 方法,例如 和 。add, removeremoveAll。
- 所有实体实例都具有唯一性 ,可用于从集合中检索实体。我们可以指定一个ID,或者一个会自动生成
viewer.entities.add({
id: "uniqueId",
});
- 使用getById检索实体。如果不存在具有所提供 ID 的实体,则返回undefined 。
const entity = viewer.entities.getById("uniqueId");
- 要获取实体或创建新实体(如果不存在),请使用getOrCreateEntity。
const entity = viewer.entities.getOrCreateEntity("uniqueId");
- 手动创建一个新实体并使用add将其添加到集合中。如果集合中已存在具有相同ID的实体,则此方法抛出。
const entity = new Entity({
id: "uniqueId",
});
viewer.entities.add(entity);
- 使用collectionChanged事件,这会在集合中添加、删除或更新实体时通知侦听器。
function onChanged(collection, added, removed, changed) {
let message = "Added ids";
for (var i = 0; i < added.length; i++) {
message += "\n" + added[i].id;
}
console.log(message);
}
viewer.entities.collectionChanged.addEventListener(onChanged);
选择(pick)
拾取(单击以选择一个对象)是我们需要与 Primitive API 进行简要交互的区域之一。使用scene.pickandscene.drillPick检索实体。
单个实例
function pickEntity(viewer, windowPosition) {
// 拾取一个对象
const picked = viewer.scene.pick(windowPosition);
// Cesium.defined是否已定义,或者不为null
if (Cesium.defined(picked)) {
// Cesium.defaultValue函数来获取该元素的id属性。
// 如果picked.id存在,则将其赋值给id变量;否则,将picked.primitive.id赋值给id变量。
const id = Cesium.defaultValue(picked.id, picked.primitive.id);
// id 的类型是 Cesium.Entity则返回id
if (id instanceof Cesium.Entity) {
return id;
}
}
return undefined;
}
区域内所有实例
function drillPickEntities(viewer, windowPosition) {
let picked, entity, i;
// drillPick拾取区域内所有实例,包括被包裹的实例
const pickedPrimitives = viewer.scene.drillPick(windowPosition);
const length = pickedPrimitives.length;
const result = [];
const 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;
}
点,广告牌和标签
通过设置位置、点和标签来创建图形点或标签。例如,在我们最喜欢的棒球队的主场放置一个点。
const viewer = new Cesium.Viewer("cesiumContainer");
const 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);
默认情况下,标签水平和垂直居中。由于标签和点共享相同的位置,因此它们在屏幕上重叠。为避免这种情况,请指定标签原点 VerticalOrigin.BOTTOM 并将像素偏移设置为 (0, -9)。
将点替换为 billboard始终面向用户的标记。
const citizensBankPark = viewer.entities.add({
position: Cesium.Cartesian3.fromDegrees(-75.166493, 39.9060534),
billboard: {
image: "/docs/images/tutorials/creating-entities/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),
},
});
3D模型
const viewer = new Cesium.Viewer("cesiumContainer");
const entity = viewer.entities.add({
position: Cesium.Cartesian3.fromDegrees(-123.0744619, 44.0503706),
model: {
uri: "../../../../Apps/SampleData/models/GroundVehicle/GroundVehicle.glb",
},
});
viewer.trackedEntity = entity;
属性系统(The property system)
我们为实体定义的所有值都存储为Property对象。例如,请参阅我们怀俄明州大纲的价值:
console.log(typeof wyoming.polygon.outline);
const wyoming = new Cesium.Entity();
wyoming.name = "Wyoming";
const 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);