449 lines
16 KiB
HTML
449 lines
16 KiB
HTML
<!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>
|