Cesium中文教程-Cesium Workshop(三)

目录

(8)加载和设计实体(Loading and Styling Entities)

(9)3D瓦片(3D Tiles)

(10)交互(Interactivity)

(11)相机模式(Camera Modes)

(12)附加内容(Extras)

(13)下一步工作(Next Steps)

开发资源(Development Resources)

Showcase your work on cesiumjs.org(展示你的作品)

Discover and process content on Cesium ion


 

(8)加载和设计实体(Loading and Styling Entities)

既然我们已经使用视图配置、影像和地形,这已经为应用程序做好了准备,那么我们可以添加应用程序的主焦点--样例geocache数据(藏宝点数据)。

为了简单可视化,Cesium支持流行的矢量格式数据GeoJson和KML,还有我们特地为描述Cesium中场景所开发的开源数据格式CZML。

无论初始化格式如何,Cesium中所有空间数据都使用实体API表示(the Entity API)。实体API提供了一种灵活可视化格式,这种格式对于Cesium的展现非常有效。一个Cesium实体(Entity)是一种数据对象,它可以与样式化的图形表示形式配对,并定位于空间和时间上,沙堡长廊提供了许多简单实体的例子(many examples of simple entities)。为了快速进入实体API的基础,从这些应用程序中抽出时间来阅读可视化空间数据的(Visualizing Spatial Data)教程。

下面是一些不同实体类型的示例:

  • Polygon
  • Polyline
  • Billboard
  • Label

一旦你掌握了实体的样子,那么使用Cesium加载数据集就变得很好理解。为了读入一个数据文件,需要创建一个适合数据格式的数据源(DataSource),其将解析托管在指定url中的数据文件,并创建一个实体收集器(EntityCollection),其包含数据集中每个地理空间对象的实体。数据源仅仅定义了数据接口-你需要的确切数据源类型取决于数据格式。例如,KML使用KmlDataSource,它是这样的:

var kmlOptions = {  
    camera : viewer.scene.camera,  
    canvas : viewer.scene.canvas,  
    clampToGround : true  
};  
// Load geocache points of interest from a KML file  
// Data from : http://catalog.opendata.city/dataset/pediacities-nyc-neighborhoods/resource/91778048-3c58-449c-a3f9-365ed203e914  
var geocachePromise = Cesium.KmlDataSource.load('./Source/SampleData/sampleGeocacheLocations.kml', kmlOptions);  

这段代码通过使用几个选项,调用KmlDataSource.load(options)来从一个KML文件中读取我们样例的藏宝点数据。对于一个KmlDataSource,相机和画布选项是必须的,clampToGround选项支持地面贴近(ground clampling),这是一种流行的显示选项,它使地面几何实体(如多边形和椭圆)符合地形,而不是曲线符合WGS84椭球面。

由于该数据是异步加载的,因此它向KmlDataSource返回一个承诺(Promise),KmlDataSource将保存我们创建的所有实体。

如果对异步函数的Promise API不熟悉的话,这里的异步主要意思是,应该对提供给.then回调函数中的数据做需要做的事情。实际上为了给场景增加这样的实体收集器,我们必须要等promise解决,然后向viewer.datasources增加KmlDataSource。 取消注释下面代码:

// Add geocache billboard entities to scene and style them  
geocachePromise.then(function(dataSource) {  
    // Add the new data as entities to the viewer  
    viewer.dataSources.add(dataSource);  
});  
 

默认情况下,新创建的实体具备可用的功能。点击将显示与实体相关的元数据信息框(Infobox),双击放大并查看实体。要停止查看实体的话,可以点击home按钮,或者点击信息框的关闭相机图标。接下来,我们将添加定制样式来改进应用程序的外观。

对于KML和CZML文件,声明样式已经创建到了文件中。然而,对于这个应用来说,我们将练习手工设置实体的样式。要这样做的话,通过等待数据源加载完成,采取一种相似的方法来实现样式例子(this styling example),然后遍历数据源中的所有实体,修改和增加属性。默认情况下,我们藏宝点标记是作为广告牌(Billboards)和标签(Labels)创建的,因此为了修改这些实体的外观,我们这样做:

// Add geocache billboard entities to scene and style them  
geocachePromise.then(function(dataSource) {  
    // Add the new data as entities to the viewer  
    viewer.dataSources.add(dataSource);  
  
    // Get the array of entities  
    var geocacheEntities = dataSource.entities.values;  
  
    for (var i = 0; i < geocacheEntities.length; i++) {  
        var entity = geocacheEntities[i];  
        if (Cesium.defined(entity.billboard)) {  
            // Entity styling code here  
        }  
    }  
});  
 

我们可以通过调整标记的锚点、移除标签以减少混乱及设置displayDistanceCondition来改善标记的外观,这样只有在相机设置的距离范围内的点才能可见。

// Add geocache billboard entities to scene and style them  
  
        if (Cesium.defined(entity.billboard)) {  
            // Adjust the vertical origin so pins sit on terrain  
            entity.billboard.verticalOrigin = Cesium.VerticalOrigin.BOTTOM;  
            // Disable the labels to reduce clutter  
            entity.label = undefined;  
            // Add distance display condition  
            entity.billboard.distanceDisplayCondition = new Cesium.DistanceDisplayCondition(10.0, 20000.0);  
        }  
 

更多distanceDisplayCondition的帮助,可以查看沙堡例子(sandcastle example)。

接下来,让我们改进每个藏宝点实体的Infobox。信息盒子的标题是实体的名字,内容是实体的表述,显示为HTML。

你可能注意到了,默认的描述不是很有用。由于我们正在显示藏宝点的位置,所以更新用来显示点的经纬度信息。

首先,将实体的位置转化为地图,然后从地图中读取经纬度,再增加到HTML表的描述中。

当点击的时候,藏宝点实体将显示一个格式好的信息框(Infobox),其中包含我们需要的数据。

// Add geocache billboard entities to scene and style them  
        if (Cesium.defined(entity.billboard)) {  
            // Adjust the vertical origin so pins sit on terrain  
            entity.billboard.verticalOrigin = Cesium.VerticalOrigin.BOTTOM;  
            // Disable the labels to reduce clutter  
            entity.label = undefined;  
            // Add distance display condition  
            entity.billboard.distanceDisplayCondition = new Cesium.DistanceDisplayCondition(10.0, 20000.0);  
            // Compute longitude and latitude in degrees  
            var cartographicPosition = Cesium.Cartographic.fromCartesian(entity.position.getValue(Cesium.JulianDate.now()));  
            var longitude = Cesium.Math.toDegrees(cartographicPosition.longitude);  
            var latitude = Cesium.Math.toDegrees(cartographicPosition.latitude);  
            // Modify description  
            // Modify description  
            var description = '' +  
                '' + "Longitude" + '' + longitude.toFixed(5) + '' +  
                '' + "Latitude" + '' + latitude.toFixed(5) + '' +  
                '';  
            entity.description = description;  
        }  
 

我们的藏宝点标记现在看起来应该是这样的:

Cesium中文教程-Cesium Workshop(三)_第1张图片

对于我们的地理藏宝应用程序,可视化一个特殊点将落在那个地区也是非常有用的。让我们加载一个GeoJson文件,其包含纽约市每个社区的多边形。加载GeoJson文件根本上与KML的加载过程非常相似。但是,在这个例子中,我们使用GeoJsonDataSource代替。像之前的数据源一样,我们需要将它添加到viewer.datasources,来实际增加数据到场景。

var geojsonOptions = {  
    clampToGround : true  
};  
// Load neighborhood boundaries from KML file  
var neighborhoodsPromise = Cesium.GeoJsonDataSource.load('./Source/SampleData/neighborhoods.geojson', geojsonOptions);  
  
// Save an new entity collection of neighborhood data  
var neighborhoods;  
neighborhoodsPromise.then(function(dataSource) {  
    // Add the new data as entities to the viewer  
    viewer.dataSources.add(dataSource);  
});  

让我们来设计加载的社区多边形。像我们之前广告牌样式一样,当数据源加载后,首先遍历社区数据源实体,同时检查是否定义了每个实体的多边形。

// Save an new entity collection of neighborhood data  
var neighborhoods;  
neighborhoodsPromise.then(function(dataSource) {  
    // Add the new data as entities to the viewer  
    viewer.dataSources.add(dataSource);  
    neighborhoods = dataSource.entities;  
  
    // Get the array of entities  
    var neighborhoodEntities = dataSource.entities.values;  
    for (var i = 0; i < neighborhoodEntities.length; i++) {  
        var entity = neighborhoodEntities[i];  
  
        if (Cesium.defined(entity.polygon)) {  
            // entity styling code here  
        }  
    }  
});  
 

因为我们现实是社区,所有使用地区作为名字重新命名每个实体。读入的原始GeoJson文件具有邻居属性。Cesium在entity.properties下存储GeoJson属性,所以我们可以这样来设置邻居名:

// entity styling code here  
  
// Use geojson neighborhood value as entity name  
entity.name = entity.properties.neighborhood;  
 

我们可以通过设置材料一个随机颜色(Color),来指定每个多边形一个新ColorMaterialProperty,而不是所有社区有相同的颜色。

// entity styling code here  
  
// Set the polygon material to a random, translucent color.  
entity.polygon.material = Cesium.Color.fromRandom({  
    red : 0.1,  
    maximumGreen : 0.5,  
    minimumBlue : 0.5,  
    alpha : 0.6  
});  
  
// Tells the polygon to color the terrain. ClassificationType.CESIUM_3D_TILE will color the 3D tileset, and ClassificationType.BOTH will color both the 3d tiles and terrain (BOTH is the default)  
entity.polygon.classificationType = Cesium.ClassificationType.TERRAIN;  
 

最后,使用一些基本样式选项给每个实体生成一个标签(Label)。为了保持整洁,无论什么3D对象都可能遮挡标签,我们可以用disableDepthTestDistance使Cesium一直在前面渲染它。

然后,要注意的是标签一直被定位在entity.position。一个多边形使用一个未定义的位置来创建,因为它有一个定义多边形边界的位置列表。我们可以通过取多边形位置的中心来生成一个位置:

// entity styling code here  
  
// Generate Polygon position  
var polyPositions = entity.polygon.hierarchy.getValue(Cesium.JulianDate.now()).positions;  
var polyCenter = Cesium.BoundingSphere.fromPoints(polyPositions).center;  
polyCenter = Cesium.Ellipsoid.WGS84.scaleToGeodeticSurface(polyCenter);  
entity.position = polyCenter;  
// Generate labels  
entity.label = {  
    text : entity.name,  
    showBackground : true,  
    scale : 0.6,  
    horizontalOrigin : Cesium.HorizontalOrigin.CENTER,  
    verticalOrigin : Cesium.VerticalOrigin.BOTTOM,  
    distanceDisplayCondition : new Cesium.DistanceDisplayCondition(10.0, 8000.0),  
    disableDepthTestDistance : 100.0  
};  
 

这给我们标记了像这样的多边形:

Cesium中文教程-Cesium Workshop(三)_第2张图片

最后,通过添加一个无人机在城市上空飞行,给NYC藏宝点增加一项高科技视图。因为飞行路线是一些时间序列的位置点,所以使用CZML文件来增加这些数据。CZML是描述时间变化的动态图形场景文件格式,主要用于在运行Cesium的web浏览器中显示。CZML描述线、点、广告牌、模型和其它图像元素,并确定它们如何随时间变化。CZML对于Cesium类同与KML对Google Earth一样,是一种标准格式,其允许通过声明样式语言(在本例中是JSON模式)使用大多数Cesium特性。

我们的CZML文件定义了一个实体(默认情况下可视化为一个点),其位置定义为不同时间点的一

系列位置。实体API中有几种属性类型可以用于处理时间动态数据,下面演示一个例子:

属性类型演示(Property Types Demo):

// Load a drone flight path from a CZML file  
var dronePromise = Cesium.CzmlDataSource.load('./Source/SampleData/SampleFlight.czml');  
  
dronePromise.then(function(dataSource) {  
    viewer.dataSources.add(dataSource);  
});  

CZML文件使用Cesium显示无人机飞行路径(Path),这是实体的属性,显示其随时间变化的位置。路径使用离散点连接到连续的直线上,然后使用插值来可视化。

最后,让我们改善无人机飞行的外观。首先,我们可以加载一个3D模型来表示无人机,并将其附加到实体上,而不是设置成一个简单的点。

  • 3D Model Demo
  • 3D Model Coloring Demo

Cesium支持加载基于glTF(GL传输格式)的3D模型,Cesium团队与科纳斯团队(Khronos group)共同开发的一种开放规范(open-specification),通过最小化文件大小和运行时处理,使应用程序高效加载3D模型。没有glTF模型的话,我们提供了一个在线转换方式(online converter),转换COLLADA和OBJ文件成glTF格式。

让我们加载一个无人机模型(Model),使其具备精致的物理外形和一些动画:

var drone;  
dronePromise.then(function(dataSource) {  
    viewer.dataSources.add(dataSource);  
    // Get the entity using the id defined in the CZML data  
    drone = dataSource.entities.getById('Aircraft/Aircraft1');  
    // Attach a 3D model  
    drone.model = {  
        uri : './Source/SampleData/Models/CesiumDrone.gltf',  
        minimumPixelSize : 128,  
        maximumScale : 1000,  
        silhouetteColor : Cesium.Color.WHITE,  
        silhouetteSize : 2  
    };  
});  
 

现在我们的模型看起来不错,但不像原来的点,无人机模型有方位,当无人机向前移动时没有转向,这看起来很奇怪。庆幸的是,Cesium提供了VelocityOrientationProperty,其根据实体在时间上前后采样的位置自动计算方向。

// Add computed orientation based on sampled positions  
drone.orientation = new Cesium.VelocityOrientationProperty(drone.position);  
 

现在,无人机模型可以按照预期转向了。

我们还可以做一件事来改善无人机飞行的外观。从远处看,这可能并不明显,但无人机的飞行路径是由看起来不自然的线段构成的,这是因为Cesium在默认情况下,使用线性插值采样点来构造路径。然后,可以配置插值选项。

  • Interpolation Demo

为了获得光滑的飞行路径,我们可以像下面这样修改插值选项:

// Smooth path interpolation  
drone.position.setInterpolationOptions({  
    interpolationDegree : 3,  
    interpolationAlgorithm : Cesium.HermitePolynomialApproximation  
});  
  • Cesium中文教程-Cesium Workshop(三)_第3张图片

(9)3D瓦片(3D Tiles)

我们团队有时会将Cesium描述为真实世界数据的3D游戏引擎。然而,使用真实世界的数据要比使用典型的电子游戏资产困难的多,因为真实数据可能具有难以置信的高分辨率,并且需要精确的可视化。庆幸的是,Cesium与开源社区合作已经开发了3D Tiles,一种用于流化大量异构三维地理空间数据集的开放规范(open specification)。

使用一种概念上类似Cesium的地形和影像流技术,3D Tiles可以查看巨大的模型,包含建筑数据、CAD(或者BIM)模型、点云和摄影测量模型,否则就不可能以交互方式进行查看。

3D Tiles Inspector是一个调式工具,它提供了一个底层视图。

下面是一些3D Tiles演示示例,展示了不同的数据格式:

  • Photogrammetry Model(摄影测量模型)
  • Building Information Model(建筑信息模型)
  • Point Cloud Model(点云模型)
  • All Formats(全部格式)

在我们的应用程序中,将使用Cesium3DTileset显示纽约所有建筑的完整3D模型来为可视化添加现实主义。NYC 瓦片托管在Cesium Ion中,可以使用IonResource.fromAssetId:

// Load the NYC buildings tileset  
var city = viewer.scene.primitives.add(new Cesium.Cesium3DTileset({ url: Cesium.IonResource.fromAssetId(3839) }));  
 

你可能注意到这些建筑在地面上有不正确的位置,幸运的是这比较容易修正。我们可以通过修改它的modelMatrix来调整tileset的位置。

可以通过将tileset的边界球转换成地图(Cartographic),然后添加所需的偏移量并重新设置模型矩阵,从而找到模型从地面到当前的偏移量:

// Adjust the tileset height so its not floating above terrain  
var heightOffset = -32;  
city.readyPromise.then(function(tileset) {  
    // Position tileset  
    var boundingSphere = tileset.boundingSphere;  
    var cartographic = Cesium.Cartographic.fromCartesian(boundingSphere.center);  
    var surface = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, 0.0);  
    var offset = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, heightOffset);  
    var translation = Cesium.Cartesian3.subtract(offset, surface, new Cesium.Cartesian3());  
    tileset.modelMatrix = Cesium.Matrix4.fromTranslation(translation);  
});  
 

现在有超过110万的建筑模型流入我们的场景!

3D Tiles允许我们使用3D Tiles样式化语言(3D Tiles styling language)来样式化部分tileset。3D Tiles样式定义了用于计算颜色(RGB和半透明)和显示Cesium3DtileFeature属性的表达式,Cesium3DtileFeature是tileset的一部分,例如城市中的单个建筑。样式化通常基于存储在tile批处理表中的特性,特征属性可以是任何东西,例如高度、名字、坐标、建设日期等等,而是内置在tileset资产中。样式使用JSON来定义,表达式是用扩展样式化的JavaScript小子集编写的。此外,样式化语言提供了一组内置函数来支持常见的数学操作。

像这样定义一个Cesium3DtileStyle:

var defaultStyle = new Cesium.Cesium3DTileStyle({  
    color : "color('white')",  
    show : true  
});  
 

这种样式只使我们纽约的所有建筑都是白色的,而且总是可见。为了实际设置tileset来使用这个样式,我们设置city.style:

city.style = defaultStyle;  
 
  • Cesium中文教程-Cesium Workshop(三)_第4张图片

    我们可以定义许多样式,下面是另一种方式,使建筑透明化:

    1.	var transparentStyle = new Cesium.Cesium3DTileStyle({  
    2.	    color : "color('white', 0.3)",  
    3.	    show : true  
    4.	});  
    

    Cesium中文教程-Cesium Workshop(三)_第5张图片

对瓦片中的每个特性使用相同的样式只是表面现象。我们可以对每个feature使用特定属性来决定其样式。下面是根据建筑物高度来渲染它们:

var heightStyle = new Cesium.Cesium3DTileStyle({  
    color : {  
        conditions : [  
            ["${height} >= 300", "rgba(45, 0, 75, 0.5)"],  
            ["${height} >= 200", "rgb(102, 71, 151)"],  
            ["${height} >= 100", "rgb(170, 162, 204)"],  
            ["${height} >= 50", "rgb(224, 226, 238)"],  
            ["${height} >= 25", "rgb(252, 230, 200)"],  
            ["${height} >= 10", "rgb(248, 176, 87)"],  
            ["${height} >= 5", "rgb(198, 106, 11)"],  
            ["true", "rgb(127, 59, 8)"]  
        ]  
    }  
});  

Cesium中文教程-Cesium Workshop(三)_第6张图片

为了在样式之间进行切换,我们可以添加更多的代码来监听HTML输入:

var tileStyle = document.getElementById('tileStyle');  
function set3DTileStyle() {  
    var selectedStyle = tileStyle.options[tileStyle.selectedIndex].value;  
    if (selectedStyle === 'none') {  
        city.style = defaultStyle;  
    } else if (selectedStyle === 'height') {  
        city.style = heightStyle;  
    } else if (selectedStyle === 'transparent') {  
        city.style = transparentStyle;  
    }  
}  
  
tileStyle.addEventListener('change', set3DTileStyle); 
 

更多关于3D Tiles的例子和怎样使用和样式化它们,可以查看3D Tiles sandcastle demos(3D瓦片沙堡演示)。

3D 瓦片演示:

  • Formats(格式)
  • Photogrammetry Model(摄影测量模型)
  • Feature Styling(特性样式)

如果你有数据,并需要帮助转换为3D瓦片,请继续关注Cesium平台更新。订阅更新(Subscribe for updates here)

(10)交互(Interactivity)

最后,让我们添加一些鼠标交互功能。为了改善藏宝点标签的可见性,当用户悬停在标记上时突出显示,我们可以改变它们的样式。

为了实现这一点,我们将使用picking(挑选),一种Cesium的特性,它从3D场景中返回给定像素位置的数据。

下面是不同类型的picking:

  • Scene.pick:返回一个给定窗口位置的,包含primitive的对象;
  • Scene.drillPick:返回一个给定窗口位置的,包含primitive的一系列对象;
  • Globe.pick:返回给定射线和地形的交点。

下面是一些实际操作重的例子:

  • Picking Demo;
  • 3D Tiles Feature Picking Demo。

由于希望在悬停触发时突出显示效果,首先我们需要创建一个鼠标操作处理程序。这就需要使用到ScreenSpaceEventHandler,在用户输入操作时触发指定函数的一组处理程序。用户操作类型ScreenSpaceEventType,运行特定的函数,传递用户操作作为参数。这里,我们将传递一个以运动为输入的函数:

  1. var handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);  
  2. handler.setInputAction(function(movement) {}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);  

接下来写突显函数。处理程序将传入一个鼠标移动,从中我们可以提取一个窗口位置,以便于pick()一起使用。如果pick返回一个广告牌对象,就知道我们正悬停在一个标签上。然后,使用学到的实体样式内容,实现突出显示样式。

  1. // If the mouse is over a point of interest, change the entity billboard scale and color  
  2. handler.setInputAction(function(movement) {  
  3.     var pickedPrimitive = viewer.scene.pick(movement.endPosition);  
  4.     var pickedEntity = (Cesium.defined(pickedPrimitive)) ? pickedPrimitive.id : undefined;  
  5.     // Highlight the currently picked entity  
  6.     if (Cesium.defined(pickedEntity) && Cesium.defined(pickedEntity.billboard)) {  
  7.         pickedEntity.billboard.scale = 2.0;  
  8.         pickedEntity.billboard.color = Cesium.Color.ORANGERED;  
  9.     }  
  10. }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);  

这样成功触发标记的突出显示样式的改变。然后,你会发现当移开光标的时候,标签仍然保持高亮。我们可以通过跟踪高亮显示的最后一个标记来修复这个问题,并恢复原始的样式。

下面是完整的功能,标记高亮和非高亮工作:

  1. // If the mouse is over a point of interest, change the entity billboard scale and color  
  2. var previousPickedEntity = undefined;  
  3. handler.setInputAction(function(movement) {  
  4.     var pickedPrimitive = viewer.scene.pick(movement.endPosition);  
  5.     var pickedEntity = (Cesium.defined(pickedPrimitive)) ? pickedPrimitive.id : undefined;  
  6.     // Unhighlight the previously picked entity  
  7.     if (Cesium.defined(previousPickedEntity)) {  
  8.         previousPickedEntity.billboard.scale = 1.0;  
  9.         previousPickedEntity.billboard.color = Cesium.Color.WHITE;  
  10.     }  
  11.     // Highlight the currently picked entity  
  12.     if (Cesium.defined(pickedEntity) && Cesium.defined(pickedEntity.billboard)) {  
  13.         pickedEntity.billboard.scale = 2.0;  
  14.         pickedEntity.billboard.color = Cesium.Color.ORANGERED;  
  15.         previousPickedEntity = pickedEntity;  
  16.     }  
  17. }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);  

就是这样,我们成功添加一个鼠标移动处理程序和标记实体悬停行为。

Cesium中文教程-Cesium Workshop(三)_第7张图片

(11)相机模式(Camera Modes)

为了展示无人机飞行,让我们来试验下相机模式。我们将保持简单,用户可以在两种基本相机模式之间替换。

  • Free Mode(自由模式):默认相机控制;
  • Drone Mode(无人操作模式):相机以固定的距离跟随无人机的飞行。

因为自由模式使用的默认控制,所以不需要任何代码。至于无人机跟随模式,我们可以使用查看器内置的实体跟踪功能,以一定偏移量来定位相机来查看无人机。即使实体在移动,这样设置相机与特定实体有一个固定的偏移量。为了跟踪实体,只需要设置viewer.trackedEntity。

要切换回自由相机模式,只需要设置查看器viewer.trackedEntity返回到未定义,然后使用camera.flyTo()返回主view。

下面是相机模式函数:

  1. // Create a follow camera by tracking the drone entity  
  2. function setViewMode() {  
  3.     if (droneModeElement.checked) {  
  4.         viewer.trackedEntity = drone;  
  5.     } else {  
  6.         viewer.trackedEntity = undefined;  
  7.         viewer.scene.camera.flyTo(homeCameraView);  
  8.     }  
  9. }  

为了将它附加到HTML输入中,我们可以附加这个函数来改变适当元素上的事件:

  1. var freeModeElement = document.getElementById('freeMode');  
  2. var droneModeElement = document.getElementById('droneMode');  
  3.   
  4. // Create a follow camera by tracking the drone entity  
  5. function setViewMode() {  
  6.     if (droneModeElement.checked) {  
  7.         viewer.trackedEntity = drone;  
  8.     } else {  
  9.         viewer.trackedEntity = undefined;  
  10.         viewer.scene.camera.flyTo(homeCameraView);  
  11.     }  
  12. }  
  13.   
  14. freeModeElement.addEventListener('change', setCameraMode);  
  15. droneModeElement.addEventListener('change', setCameraMode);  

最后,当用户双击实体时,其将被自动跟踪。如果用户通过单击来开始跟踪无人机,那么我们可以添加一些处理来自动更新UI:

  1. viewer.trackedEntityChanged.addEventListener(function() {  
  2.     if (viewer.trackedEntity === drone) {  
  3.         freeModeElement.checked = false;  
  4.         droneModeElement.checked = true;  
  5.     }  
  6. });  

这就是我们两个相机模式-现在可以自由切换到无人机相机视图,结果看起来像这样:

Cesium中文教程-Cesium Workshop(三)_第8张图片

(12)附加内容(Extras)

其余的代码只是增加了一些额外的可视化选项。类似于我们之前与HTML元素的交互,可以附加监听函数来触发影子,和社区多边形显示。

让我们从创建一个简单方式来触发切换社区多边形开始。通常,可以通过Entity.show设置可见性来隐藏实体,但是,这只设置了单个实体的可见性,我们希望同时设置隐藏或显示所有社区实体。

我们可以这样做,将所有社区实体添加到父实体来实现这一点,正如示例(this example)中所示或者通过简单地使用EntityCollection的show属性。然后,我们可以通过更改neighborhoods.show的值来同时设置所有子实体的可见性:

  1. var neighborhoodsElement =  document.getElementById('neighborhoods');  
  2.   
  3. neighborhoodsElement.addEventListener('change'function (e) {  
  4.     neighborhoods.show = e.target.checked;  
  5. });  

可以使用相类似的方式来改变阴影的可见性:

  1. var shadowsElement = document.getElementById('shadows');  
  2.   
  3. shadowsElement.addEventListener('change'function (e) {  
  4.     viewer.shadows = e.target.checked;  
  5. });  

最后,由于3D瓦片可能不会立即加载,我们可以增加一个加载指示器,其只有在加载了tileset之后才被删除(因此应答也就得到了解决)。

  1. // Finally, wait for the initial city to be ready before removing the loading indicator.  
  2. var loadingIndicator = document.getElementById('loadingIndicator');  
  3. loadingIndicator.style.display = 'block';  
  4. city.readyPromise.then(function () {  
  5.     loadingIndicator.style.display = 'none';  
  6. });  

(13)下一步工作(Next Steps)

祝贺哦~!~!你已经成功完成了CesiumJS应用程序!可以随意探索和试验这里提供的代码,以进一步学习Cesium。我们非常欢迎你来Cesium社区,并期待看到你使用CesiumJS库构建的惊人应用程序。

接下来是什么呢?

开发资源(Development Resources)

对于本教程以及余下的Cesium开发中,我们鼓励你依靠以下资源:

  • Reference Documentation(参考文献):一个Cesium API的完成指南,包含许多代码片段;
  • Sandcastle(沙堡):具有大量代码示例的实时编码环境;
  • Tutorials(教程):Cesium开发领域的详细介绍;
  • Cesium Forum(Cesium论坛):询问和回答Cesium相关问题的资源。

任何时候,当你遇到困难的时候,这些资源中很有可能会有你想要的答案。

Showcase your work on cesiumjs.org(展示你的作品)

我们喜欢分享Cesium社区创建的所有惊人的应用程序。世界各地的开发者已经创建了比我们想象的更有趣的应用程序!只要你的应用程序准备好与世界分享,请联系我们,在CesiumJS演示页面(CesiumJS Demos Page)展示你的应用程序。更多关于你应用程序展示的信息,请参阅本文(this blog post)。

Discover and process content on Cesium ion

Cesium ion是一个新的商业平台,由web服务和工具组成来完善CesiumJS的可视化,创建一个完整的3D地图平台。Cesium团队对ion特别感兴趣,因为它是我们围绕CesiumJS构建的第一个产品,用来支持开发开源CesiumJS。

ion的愿景包含订阅:

  • 3D内容,例如影像、地形、3Dtilesets、glTF模型,这些是从开放数据和商业数据提供者策划(curated)的;
  • 3D瓦片化和托管你自己大量数据集,例如影像、地形、摄影测量图、点云、BIM、CAD、3D建筑和矢量数据;
  • 分析,例如测量工具、体积和可见性计算和地形配置文件;
  • 创建无需编码3D地图的地图制作和共享工作流程。

更多信息请访问cesium.com。

Happy developing!

 

 

 

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(Cesium中文教程,Cesium中文教程)