learning_cesium/workshop.html

449 lines
16 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en">
<head>
<!-- Use correct character set. -->
<meta charset="utf-8">
<!-- Tell IE to use the latest, best version. -->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!-- Make the application on mobile take up the full browser screen and disable user scaling. -->
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
<title>Learning Cesium!</title>
<script src="./Build/Cesium/Cesium.js"></script>
<style>
@import url(./Build/Cesium/Widgets/widgets.css);
html, body, #cesiumContainer {
width: 100%; height: 100%; margin: 0; padding: 0; overflow: hidden;
}
.backdrop {
display: inline-block;
background: rgba(42, 42, 42, 0.7);
border-radius: 5px;
border: 1px solid #444;
padding: 5px 10px;
color: #fff;
line-height: 150%;
font-size: small;
}
#heightSliderLabel, #heightValue {
vertical-align: top;
}
.backdrop a:link, .backdrop a:visited, .backdrop a:hover {
color: #fff
}
.loadingIndicator {
display: none;
position: absolute;
top: 50%;
left: 50%;
margin-top: -33px;
margin-left: -33px;
width: 66px;
height: 66px;
background: url(Source/Images/ajax-loader.gif) center no-repeat;
}
.cover {
display: none;
position: absolute;
background-color: rgba(0, 0, 0, 0.75);
top: 0;
left: 0;
right: 0;
bottom: 0;
}
#menu {
position: absolute;
left: 10px;
top: 10px;
}
.nowrap {
white-space: nowrap;
}
html, body, #cesiumContainer {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
overflow: hidden;
font-family: sans-serif;
background: #000;
}
button.cesium-infoBox-camera {
display: none;
}
#3DTiles {
padding-top: 10px;
}
</style>
</head>
<body>
<div id="cesiumContainer"></div>
<!-- Some input elements for our app. -->
<div class="backdrop" id="menu">
<h2>Sample NYC Geocaches</h2>
<span><strong>Camera Mode</strong></span>
<div class="nowrap">
<input id="freeMode" name="source" type="radio" checked/>
<label for="freeMode">Free</label>
</div>
<div class="nowrap">
<input id="droneMode" name="source" type="radio"/>
<label for="droneMode">Drone View</label>
</div>
<br>
<span><strong>3d Tile Styling</strong></span>
<div class="nowrap">
<select id="tileStyle">
<option value="none">None</option>
<option value="height">Height</option>
<option value="transparent">Transparent</option>
</select>
</div>
<br>
<span><strong>Display Options</strong></span>
<div class="nowrap">
<input id="shadows" type="checkbox"/>
<label for="shadows">Shadows</label>
</div>
<div class="nowrap">
<input id="neighborhoods" type="checkbox" checked/>
<label for="neighborhoods">Neighborhoods</label>
</div>
<br>
</div>
<div id="loadingIndicator" class="cover">
<div id="loadingIcon" class="loadingIndicator"></div>
</div>
<script>
Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI5ZjRjNTZkNC01NDYxLTRhMjQtOGEwZC1kZjA3YzQ5YTJlZDkiLCJpZCI6MjYwODQsInNjb3BlcyI6WyJhc3IiLCJnYyJdLCJpYXQiOjE1ODcxOTMwODN9.prGsSKyAW_9Ow5zHYPhbm3LsQL-ApQw5-5PNJkDaHi8';
var viewer = new Cesium.Viewer('cesiumContainer',{
scene3DOnly: true,
selectionIndicator: false,
baseLayerPicker: false
});
// 移除默认的底图
viewer.imageryLayers.remove(viewer.imageryLayers.get(0));
// 添加哨兵影像 Sentinel-2 imagery
viewer.imageryLayers.addImageryProvider(new Cesium.IonImageryProvider({ assetId : 3954 }));
viewer.terrainProvider = Cesium.createWorldTerrain({
requestWaterMask : true, // required for water effects
requestVertexNormals : true // required for terrain lighting
});
// 确保地形后面的物体能够被正确遮挡
viewer.scene.globe.depthTestAgainstTerrain = true;
// 使场景中的灯光随着时间的变化而变化。如果你缩小,你会看到地球的那部分是黑暗的,因为太阳已经在那部分落下了。
viewer.scene.globe.enableLighting = true;
// Create an initial camera view
var initialPosition = new Cesium.Cartesian3.fromDegrees(-73.998114468289017509, 40.674512895646692812, 2631.082799425431);
var initialOrientation = new Cesium.HeadingPitchRoll.fromDegrees(7.1077496389876024807, -31.987223091598949054, 0.025883251314954971306);
var homeCameraView = {
destination : initialPosition,
orientation : {
heading : initialOrientation.heading,
pitch : initialOrientation.pitch,
roll : initialOrientation.roll
}
};
// Set the initial view
viewer.scene.camera.setView(homeCameraView);
// Add some camera flight animation options
homeCameraView.duration = 2.0;
homeCameraView.maximumHeight = 2000;
homeCameraView.pitchAdjustHeight = 2000;
homeCameraView.endTransform = Cesium.Matrix4.IDENTITY;
// 覆盖 homeButton 的点击事件
viewer.homeButton.viewModel.command.beforeExecute.addEventListener(function (e) {
e.cancel = true;
viewer.scene.camera.flyTo(homeCameraView);
});
// Set up clock and timeline.
viewer.clock.shouldAnimate = true; // make the animation play when the viewer starts
viewer.clock.startTime = Cesium.JulianDate.fromIso8601("2017-07-11T16:00:00Z");
viewer.clock.stopTime = Cesium.JulianDate.fromIso8601("2017-07-11T16:20:00Z");
viewer.clock.currentTime = Cesium.JulianDate.fromIso8601("2017-07-11T16:00:00Z");
viewer.clock.multiplier = 2; // sets a speedup
viewer.clock.clockStep = Cesium.ClockStep.SYSTEM_CLOCK_MULTIPLIER; // tick computation mode
viewer.clock.clockRange = Cesium.ClockRange.LOOP_STOP; // loop at the end
viewer.timeline.zoomTo(viewer.clock.startTime, viewer.clock.stopTime); // set visible range
/*
Cesium 中对KML的支持还不是很完善但实现了大部分标准和Google的gx扩展命名空间。
Cesium 提供KmlDataSource 类来解析 KML和KMZ数据
配置项中 camera 和 canvas 是必需的;
KmlDataSource 实例的 load 方法是异步的,返回一个 Promise 实例对象,
可在请求完成后的 then 方法后处理加载的数据源
*/
var kmlOptions = {
camera : viewer.scene.camera,
canvas : viewer.scene.canvas,
clampToGround : true//使得实体贴合地形,而不是弯曲的WGS84椭球面
};
var geocachePromise = Cesium.KmlDataSource.load('SampleData/sampleGeocacheLocations.kml', kmlOptions);
// Add geocache billboard entities to scene and style them
geocachePromise.then(function(dataSource) {
// 将数据源中的数据作为实体添加到 viewer 实例中
viewer.dataSources.add(dataSource);
// 获取实体数组
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
// 调整实体垂直方向上的位置,使其于地形贴合,不至于被地形遮挡
entity.billboard.verticalOrigin = Cesium.VerticalOrigin.BOTTOM;
// 取消显示标注
entity.label = undefined;
// 添加可见范围
entity.billboard.distanceDisplayCondition = new Cesium.DistanceDisplayCondition(10.0, 20000.0);
// 转换坐标,将实体的位置坐标 Cartesian3 转成经纬度 Cartographic ,用于显示
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);
// 修改实体描述
var description = '<table class="cesium-infoBox-defaultTable cesium-infoBox-defaultTable-lighter"><tbody>' +
'<tr><th>' + "Longitude" + '</th><td>' + longitude.toFixed(5) + '</td></tr>' +
'<tr><th>' + "Latitude" + '</th><td>' + latitude.toFixed(5) + '</td></tr>' +
'<tr><th>' + "JulianDate" + '</th><td>' + Cesium.JulianDate.now() + '</td></tr>' +
// '<tr><th>' + "entity.position" + '</th><td>' + entity.position.getValue(Cesium.JulianDate.now()) + '</td></tr>' +
// '<tr><th>' + "fromDate" + '</th><td>' + entity.position.getValue(Cesium.JulianDate.fromDate(new Date("2019-12-12"))) + '</td></tr>' +
// '<tr><th>' + "cartographicPosition.latitude" + '</th><td>' + cartographicPosition.latitude + '</td></tr>' +
'</tbody></table>';
entity.description = description;
}
}
});
/**
* 加载 GeoJson 数据
* 使用 GeoJsonDataSource 类解析 GeoJson 数据
*/
var geojsonOptions = {
clampToGround : true //贴合地形
};
// 加载geojson格式的社区数据
var neighborhoodsPromise = Cesium.GeoJsonDataSource.load('SampleData/sampleNeighborhoods.geojson', geojsonOptions);
// 用于保存添加的实体集合
var neighborhoods;
neighborhoodsPromise.then(function(dataSource) {
// 将请求获得的数据添加到 viewer 中
viewer.dataSources.add(dataSource);
neighborhoods = dataSource.entities;
// 获取实体数组
var neighborhoodEntities = dataSource.entities.values;
for (var i = 0; i < neighborhoodEntities.length; i++) {
var entity = neighborhoodEntities[i];
if (Cesium.defined(entity.polygon)) {
// Cesium 将 GeoJson 的属性数据存储在实体的properties 属性中
entity.name = entity.properties.neighborhood;
// 使用随机颜色样式作为填充材料.
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;
// 获取面的位置坐标信息
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),//设置于 Camera 距离的显示范围
disableDepthTestDistance : 100.0
};
}
}
});
/**
* 加载飞机模型
* 1、CZML数据将时间动态图形加载进来设置 clock 将时间于时态数据对齐
* 2、获取数据源中的轨迹移动点绑定模型
*/
// Load a drone flight path from a CZML file
var dronePromise = Cesium.CzmlDataSource.load('SampleData/sampleFlight.czml');
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');
// 挂载 3维模型
drone.model = {
uri : 'SampleData/Models/CesiumDrone.gltf',
minimumPixelSize : 128,
maximumScale : 1000,
silhouetteColor : Cesium.Color.WHITE,
silhouetteSize : 2
};
// VelocityOrientationProperty 会在时间上向前和向后采样的实体的位置,自动计算实体的方向
drone.orientation = new Cesium.VelocityOrientationProperty(drone.position);
// 对实体的位置 position 进行插值,平滑路径轨迹
drone.position.setInterpolationOptions({
interpolationDegree : 3,
interpolationAlgorithm : Cesium.HermitePolynomialApproximation
});
});
/**
* 加载 3D Tile 数据
* Cesium 提供 Cesium3DTileset 类来解析 3D Tile 数据
*
*/
//加载 Cesium Ion 中的纽约市的3D模型
var city = viewer.scene.primitives.add(new Cesium.Cesium3DTileset({ url: Cesium.IonResource.fromAssetId(75343) }));
var defaultStyle = new Cesium.Cesium3DTileStyle({
color : "color('white')",
show : true
});
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)"]
]
}
});
city.style = heightStyle;
//绑定样式切换事件
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);
/**
* 事件交互
* 通过 Scene.pick/Scene.drillPick/Globe.pick 可以获取鼠标点击的位置下的实体。
*
* 事件处理:
* 通过 ScreenSpaceEventHandler 类处理用户输入事件。
* 构造器new Cesium.ScreenSpaceEventHandler(element)
* 主要方法:
* setInputAction(action, type, modifier)
* action事件回调函数
* type事件类型可选值参考https://cesium.com/docs/cesiumjs-ref-doc/ScreenSpaceEventType.html
* 常用 Cesium.ScreenSpaceEventType.LEFT_CLICK鼠标左键单击
* Cesium.ScreenSpaceEventType.MOUSE_MOVE鼠标移动
*/
var handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
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);
/**
* 控制 相机 模式
* viewer.trackedEntity :视角追踪实体的位置
*/
var freeModeElement = document.getElementById('freeMode');
var droneModeElement = document.getElementById('droneMode');
// Create a follow camera by tracking the drone entity
function setViewMode() {
if (droneModeElement.checked) {
viewer.trackedEntity = drone;
} else {
viewer.trackedEntity = undefined;
viewer.scene.camera.flyTo(homeCameraView);
}
}
freeModeElement.addEventListener('change', setViewMode);
droneModeElement.addEventListener('change', setViewMode);
viewer.trackedEntityChanged.addEventListener(function() {
if (viewer.trackedEntity === drone) {
freeModeElement.checked = false;
droneModeElement.checked = true;
}
});
//-----------------------------------------------------------
var neighborhoodsElement = document.getElementById('neighborhoods');
neighborhoodsElement.addEventListener('change', function (e) {
neighborhoods.show = e.target.checked;
});
var loadingIndicator = document.getElementById('loadingIndicator');
loadingIndicator.style.display = 'block';
city.readyPromise.then(function () {
loadingIndicator.style.display = 'none';
});
</script>
</body>
</html>