cesium一个完整个案例
2019-03-19 16:30:49 来源:admin 点击:3601
cesium安装
http://www.zfx.fun/web/34.html
创建一个viewer
http://www.zfx.fun/web/36.html
增加修改图层
http://www.zfx.fun/web/45.html
增加修改地形
http://www.zfx.fun/web/39.html
配置其他功能
灯光
viewer.scene.globe.enableLighting = true;
接着,在我们开始初始化视图之前,让我们去认识下Cesium的类型:
Cartesian3 : 一个3D的笛卡尔点 - 当被用作位置时,它与地球的中心是相对的,使用地球固定框架(ECR)。
Cartographic : 由纬度/经度(弧度)定义的位置和地球表面的高度。
Heading Pitch Roll :一种旋转(在弧度上)关于在中轴上的局部轴的旋转。标题是关于负z轴的旋转。纵轴是负y轴的旋转。滚动是关于正x轴的旋转。
Quaternion : 3D通过旋转表示为4D坐标。
这些是在场景中定位和定位Cesium物体所必需的基本类型,并且有许多有用的转换方法。
现在让我们把我们的场景设在纽约市,我们的数据就在那里。
Camera Control(相机控件)
Camera 是 viewer.scene 的属性,控制当前可见的内容。我们可以通过设置正确的位置和方向来控制相机, 或者通过使用Cesium camera API来操作相机,该API可以灵活的指定相机的位置和方向。
以下是一些常用的方法:
Camera.setView(options) :在特定的位置和方向设置相机
Camera.zoomIn(amount) : 沿着视图矢量向前移动相机。
Camera.zoomOut(amount) : 沿着视图矢量向后移动相机。
Camera.flyTo(options) : 从当前位置移动到新位置的运动。
Camera.lookAt(target, offset) : 定位和定位摄像机,以给定的偏移量来观察目标点。
Camera.move(direction, amount) : 移动相机到特定方向。
Camera.rotate(axis, angle) : 围绕轴旋转。
添加实体
http://www.zfx.fun/web/44.html
添加 3D Tiles
// Load the NYC buildings tileset var city = viewer.scene.primitives.add( new Cesium.Cesium3DTileset({ url: 'https://beta.cesium.com/api/assets/1461?access_token=eyJhbGciOiJIUzI1NiIsInR5cCI6Ikp XVCJ9.eyJqdGkiOiJkYWJmM2MzN S02OWM5LTQ3OWItYjEyYS0xZmNlODM5ZDNkMT YiLCJpZCI6NDQsImFzc2V0cyI6WzE0NjFdLCJpYXQiOjE0OTkyNjQ3NDN9.vuR75S qPDKcggvUrG_vpx0Av02jdiAxnnB1fNf-9f7s', maximumScreenSpaceError: 16 // default value }));
就像添加普通的3D模型一样,我们指定一个url来对数据进行检索,然后将对象添加到场景中。在本例中,我们将tileset添加到scene.primitive而不是scene.entity,因为3D Tiles还不是实体API的一部分。 maximumScreenSpaceError指定了一个给定的视图中Cesium的具体细节,数字越低,视觉效果就越好。 高细节的视觉效果当然是伴随着性能成本的,所以当你改变这个设置时wbe很清楚。
你可能会注意到建筑物在地面上没有正确的位置。这是3D tilesets面临的一个常见问题,幸运的是,它很容易修复。 我们可以通过修改modelMatrix模型矩阵来调整位置。
我们可以通过将tileset的边界球体转换成一个Cartographic(地图),然后添加所需的偏移量和重置模型矩阵来找到模型当前的偏移量。
var heightOffset = -32; city.readyPromise.then(function(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 styling language来设定我们的样式部分。 3D Tiles风格定义了用来评估颜色(RGB和半透明)的表达式,并显示了一个Cesium3DTileFeature特性的属性。这是城市的一部分,就像城市里的个人建筑一样。 样式基于特征属性并且存储在 tile’s batch table中。特征属性可以是高度,名称,坐标,构建日期等,但它是建立在tileset上的。风格是用JSON和表达式定义的,在用于样式化的JavaScript的一小部分中编写。 此外,样式化语言提供了一组内置函数来支持常见的数学操作。
一个Cesium3DTileStyle 的定义如下所示:
var defaultStyle = new Cesium.Cesium3DTileStyle({ color : "color('white')", show : true });
这种风格会使我们纽约的所有建筑都变得白色,而且总是可见的。为了真正地让tileset使用这种风格,我们设置了city.style
:
city.style = defaultStyle;
我们可以定义任意多的样式。这是另一种,让建筑变得透明:
var transparentStyle = new Cesium.Cesium3DTileStyle({ color : "color('white', 0.3)", show : true });
我们还可以使用特定于每个特性的属性来确定样式。这里有一个例子,根据他们的高度来给建筑物颜色:
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)"] ] } });
为了在样式之间进行切换,我们可以添加更多的代码来侦听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);
Interactivity(交互)
最后,让我们添加一些鼠标交互。为了提高我们的geocache标记的可见性,当用户在一个标记上停留以突出显示时,我们可以改变他们的样式。
为了实现这一点,我们将使用picking,它从3D场景中返回数据,并在查看器画布上显示一个像素位置。
有几种不同类型的选择。
Scene.pick : 在给定的窗口位置返回一个包含primitive的对象。
Scene.drillPick : 返回一个包含给定窗口位置的所有primitives的对象列表。
Globe.pick : 返回给定光线与地形的交点。
下面是一些例子:
Picking Demo
3D Tiles Feature Picking Demo
由于我们希望在悬浮上触发高光效果,所以首先需要创建一个鼠标事件。使用ScreenSpaceEventHandler, 一组在用户输入操作上触发指定功能的处理程序。 ScreenSpaceEventHandler.setInputAction() 监听操作类型 ScreenSpaceEventType的种类, 并运行一个特定的函数,将用户操作作为参数传递。这里,我们将传递一个函数,在鼠标移动时触发:
var handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas); handler.setInputAction(function(movement) {}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
下面我们来写一下我们的高亮显示函数。处理程序将传入鼠标移动事件,从中我们可以提取一个窗口位置,以便使用pick()
。 如果pick返回一个billboard对象,我们知道我们在一个标记上。然后,使用我们所学到的Entity
样式,我们可以应用一个突出显示样式。
handler.setInputAction(function(movement) { var pickedPrimitive = viewer.scene.pick(movement.endPosition); var pickedEntity = (Cesium.defined(pickedPrimitive))? pickedPrimitive.id : undefined; if (Cesium.defined(pickedEntity) && Cesium.defined(pickedEntity.billboard)) { pickedEntity.billboard.scale = 2.0; pickedEntity.billboard.color = Cesium.Color.ORANGERED; } }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
这成功地触发了标记的高亮样式更改。但是,当我们将光标移开时,您会注意到这些标记仍然突出显示。我们可以通过跟踪高亮显示的最后一个标记来修复它,并恢复原来的样式。
以下是完整的功能代码,带有标记高亮和未高亮显示的工作:
var previousPickedEntity = undefined; handler.setInputAction(function(movement) { var pickedPrimitive = viewer.scene.pick(movement.endPosition); var pickedEntity = (Cesium.defined(pickedPrimitive)) ? pickedPrimitive.id : undefined; if (Cesium.defined(previousPickedEntity)) { previousPickedEntity.billboard.scale = 1.0; previousPickedEntity.billboard.color = Cesium.Color.WHITE; } if (Cesium.defined(pickedEntity) && Cesium.defined(pickedEntity.billboard)) { pickedEntity.billboard.scale = 2.0; pickedEntity.billboard.color = Cesium.Color.ORANGERED; previousPickedEntity = pickedEntity; } }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
就是这样!我们现在已经成功地为我们的标记实体添加了鼠标移动处理程序和悬停行为。
Camera Modes(相机模式)
为了展示我们的无人机飞行,让我们来试验一下相机模式。我们将简单地使用两种基本的相机模式,用户可以在其中切换。
Free Mode : 默认的相机控件
Drone Mode :让摄像机跟随无人机在一个固定的距离之外飞行
free mode(自由模式)不需要任何代码,因为它使用默认控件。至于drone follow mode(无人机跟随模式),我们可以将摄像头定位在无人机上,并使用viewer内置的实体跟踪功能。这使得相机即使在它移动的时候,在一个指定的实体中也处于固定的偏移量。 为了跟踪一个实体,我们简单的设置viewer.trackedEntity.
为了切换到免费的相机模式,我们可以设置 viewer.trackedEntity
来返回到未定义的,然后使用camera.flyTo()
返回到我们的主视图。
这是相机模式功能:
function setViewMode() { if (droneModeElement.checked) { viewer.trackedEntity = drone; } else { viewer.trackedEntity = undefined; viewer.scene.camera.flyTo(homeCameraView); } }
为了将这个附加到HTML输入,我们可以附加这个函数来change
更改元素上的事件:
var freeModeElement = document.getElementById('freeMode'); var droneModeElement = document.getElementById('droneMode'); function setViewMode() { if (droneModeElement.checked) { viewer.trackedEntity = drone; } else { viewer.trackedEntity = undefined; viewer.scene.camera.flyTo(homeCameraView); } } freeModeElement.addEventListener('change', setCameraMode); droneModeElement.addEventListener('change', setCameraMode);
最后,当用户双击这些实体时,将自动跟踪实体。如果用户开始通过点击来跟踪无人机,我们可以添加一些处理来自动更新用户界面:
viewer.trackedEntityChanged.addEventListener(function() { if (viewer.trackedEntity === drone) { freeModeElement.checked = false; droneModeElement.checked = true; } });
这就是我们的两种相机模式——我们现在可以自由地切换到一个像这样的无人机摄像头视图:
Extras
其余的代码只是添加了一些额外的可视化选项,类似于我们之前与HTML元素的交互,我们可以附加侦听器函数来切换阴影,以及附近的多边形可见性。
var shadowsElement = document.getElementById('shadows'); var neighborhoodsElement = document.getElementById('neighborhoods'); shadowsElement.addEventListener('change', function (e) { viewer.shadows = e.target.checked; }); neighborhoodsElement.addEventListener('change', function (e) { neighborhoods.show = e.target.checked; tileStyle.value = 'transparent'; city.style = transparentStyle; });
由于由于3D瓷砖可能不会立即加载,我们还可以添加一个加载指示器,只有在tileset加载时才会移除 。
var loadingIndicator = document.getElementById('loadingIndicator'); loadingIndicator.style.display = 'block'; city.readyPromise.then(function () { loadingIndicator.style.display = 'none'; });