cesium-examples/map/examples/fly.html

513 lines
20 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>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>三维飞行</title>
<link href="../Build/Cesium/Widgets/widgets.css" rel="stylesheet">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script type="text/javascript" src="../Build/Cesium/Cesium.js"></script>
<script type="text/javascript" src="../common/js/Cesium_init.js"></script>
<style>
html,body
{
width:100%;
height:100%;
padding:0;
margin:0
}
</style>
</head>
<body>
<div id = "cesiumContainer" style="width:100%;height:100%;">
</div>
<div id="fly_operator_container" style="position:absolute;z-index:9;top:10px;left:10px;">
<button onclick="initFly()">初始化</button>
<button onclick="startFly()">开始飞行</button>
<button onclick="pauseFly()">暂停飞行</button>
<button onclick="aircraftView()">跟随视角</button>
<button onclick="flyBack()">向后飞行</button>
<button onclick="flyForward()">向前飞行</button>
<button onclick="stopFly(true)">结束飞行</button>
<div style="color:white;display:none" class="flyByKeywordContainer">
<table class="infoPanel">
<tbody>
<tr>
<td>左右: <span id="heading"></span>°</td>
</tr>
<tr>
<td>← 左/→ 右</td>
</tr>
<tr>
<td>上下: <span id="pitch"></span>°</td>
</tr>
<tr>
<td>↑ 上/↓ 下</td>
</tr>
<tr>
<td>倾斜: <span id="roll"></span>°</td>
</tr>
<tr>
<td>← + shift 左/→ + shift 右</td>
</tr>
<tr>
<td>速度: <span id="speed"></span>m/s</td>
</tr>
<tr>
<td>↑ + shift 加速/↓ + shift 减速</td>
</tr>
<tr>
<td>跟随飞机
<input id="fromBehind" type="checkbox">
</td>
</tr>
</tbody>
</table>
</div>
</div>
<script>
//地图资源
var GoogleMap = ImageryProviderWebExtendTool.createGoogleMapsByUrl(Cesium, { url: "http://mt1.google.cn/vt/lyrs=s&hl=zh-CN&x={x}&y={y}&z={z}" });
var viewer = new Cesium.Viewer('cesiumContainer', {
imageryProvider: GoogleMap,
shouldAnimate : true,
selectionIndicator: false,
baseLayerPicker:false,
homeButton:false,
animation: true,
timeline:true,
geocoder: false,
sceneModePicker: false,
navigationHelpButton: false,
infoBox: false,
fullscreenButton: false
});
var mFlySpeed = 10;
var mFlyPath = [];
/**
* 初始化飞行数据
**/
function initFly()
{
pauseFly();
// 数据
if(!mFlyPath || mFlyPath.length == 0)
{
mFlyPath[0] = [
{longitude:116.538799, dimension:39.9948, height:0, time:0},
{longitude:116.130034, dimension:38.291387, height:5000, time:120},
{longitude:116.415192, dimension:34.841955, height:5000, time:240},
{longitude:117.261468, dimension:31.831171, height:5000, time:360},
{longitude:115.881671, dimension:28.70164, height:5000, time:480},
{longitude:116.120835, dimension:24.308311, height:5000, time:600},
{longitude:113.269254, dimension:23.13956, height:0, time:720}];
//设置初始位置
viewer.camera.flyTo({
destination : Cesium.Cartesian3.fromDegrees(mFlyPath[0][0].longitude , mFlyPath[0][0].dimension , 100000),
orientation: {
heading : Cesium.Math.toRadians(20.0), // 方向
pitch : Cesium.Math.toRadians(-90.0),// 倾斜角度
roll : 0
},
pitchAdjustHeight: -90, // 如果摄像机飞越高于该值,则调整俯仰俯仰的俯仰角度,并将地球保持在视口中。
maximumHeight:5000, // 相机最大飞行高度
flyOverLongitude: 100, // 如果到达目的地有2种方式设置具体值后会强制选择方向飞过这个经度
});
}
// 起始时间
let start = new Cesium.JulianDate();
// 结束时间
let stop = Cesium.JulianDate.addSeconds(start, (mFlyPath[0].length-1)*120,new Cesium.JulianDate());
// 设置始时钟始时间
viewer.clock.startTime = start.clone();
// 设置时钟当前时间
viewer.clock.currentTime = start.clone();
// 设置始终停止时间
viewer.clock.stopTime = stop.clone();
// 时间速率,数字越大时间过的越快
viewer.clock.multiplier = mFlySpeed;
// 循环执行
viewer.clock.clockRange = Cesium.ClockRange.LOOP_STOP;
let data = mFlyPath;
for(let j=0; j<data.length; j++)
{
let property = new Cesium.SampledPositionProperty();
for(let i=0; i<data[j].length; i++){
let time = Cesium.JulianDate.addSeconds(start, data[j][i].time, new Cesium.JulianDate());
let position = Cesium.Cartesian3.fromDegrees(data[j][i].longitude, data[j][i].dimension, data[j][i].height);
// 添加位置,和时间对应
property.addSample(time, position);
}
// 添加模型
viewer.entities.add({
id: "fly",
// 和时间轴关联
availability : new Cesium.TimeIntervalCollection([new Cesium.TimeInterval({
start : start,
stop : stop
})]),
position: property,
//基于位置移动自动计算方向.
orientation: new Cesium.VelocityOrientationProperty(property),
// 模型数据,跨域,模型文件必须放本地
model: {
uri: '../../3dmap/Apps/SampleData/models/CesiumAir/Cesium_Air.gltf',
scale: 6,
minimumPixelSize: 64
},
//路径
path : {
resolution : 1,
//设置航线样式,线条颜色,内发光粗细,航线宽度等
material : new Cesium.PolylineGlowMaterialProperty({
glowPower : 0.1,
color : Cesium.Color.YELLOW
}),
width : 30
}
});
}
}
/**
* 开始飞行
**/
function startFly()
{
viewer.clock.shouldAnimate = true;
}
/**
* 暂停飞行
**/
function pauseFly()
{
viewer.clock.shouldAnimate = false;
}
/**
* 顶部视图
**/
function topView()
{
viewer.trackedEntity = undefined;
viewer.zoomTo(viewer.entities, new Cesium.HeadingPitchRange(0, Cesium.Math.toRadians(-90)));
}
/**
* 侧面视图
**/
function sideView()
{
viewer.trackedEntity = undefined;
viewer.zoomTo(viewer.entities, new Cesium.HeadingPitchRange(Cesium.Math.toRadians(-90), Cesium.Math.toRadians(-15), 7500));
}
/**
* 跟随视图
**/
function aircraftView()
{
viewer.trackedEntity = viewer.entities.getById("fly");
}
/**
* 向后飞行
**/
function flyBack()
{
mFlySpeed = -10;
viewer.clock.multiplier = mFlySpeed;
}
/**
* 向前飞行
**/
function flyForward()
{
mFlySpeed = 10;
viewer.clock.multiplier = mFlySpeed;
}
/**
* 自定义路线飞行
**/
function customFly()
{
window.PolyLinePrimitive = (function(){
function _(positions)
{
this.options = {
polyline : {
show : true,
positions : [],
material : Cesium.Color.CORNFLOWERBLUE,
width : 5
}
};
this.positions = positions;
this._init();
}
_.prototype._init = function(){
var _self = this;
var _update = function(){
return _self.positions;
};
//实时更新polyline.positions
this.options.polyline.positions = new Cesium.CallbackProperty(_update,false);
viewer.entities.add(this.options);
};
return _;
})();
var handler = new Cesium.ScreenSpaceEventHandler(viewer.canvas);
var positions = [];
var poly = undefined;
var lnglatPositions=[];
handler.setInputAction(function(movement)
{
//屏幕坐标转成经纬度坐标
var cartesian = viewer.scene.camera.pickEllipsoid(movement.position,viewer.scene.globe.ellipsoid);
if(positions.length == 0)
{
positions.push(cartesian.clone());
}
positions.push(cartesian);
var ray = viewer.camera.getPickRay(movement.position);;
cartesian= viewer.scene.globe.pick(ray, viewer.scene);
if (!cartesian)
return;
let cartographic = Cesium.Cartographic.fromCartesian(cartesian);
let lng = Cesium.Math.toDegrees(cartographic.longitude);//经度值
let lat = Cesium.Math.toDegrees(cartographic.latitude);//纬度值
lnglatPositions.push({longitude:lng, dimension:lat, height:5000, time:lnglatPositions.length*120});
},Cesium.ScreenSpaceEventType.LEFT_CLICK);
//鼠标移动事件
handler.setInputAction(function(movement){
var cartesian = viewer.camera.pickEllipsoid(movement.endPosition,viewer.scene.globe.ellipsoid);
if(positions.length >= 2)
{
if (!Cesium.defined(poly)) {
poly = new PolyLinePrimitive(positions);
}else{
positions.pop();
cartesian.y += (1 + Math.random());
positions.push(cartesian);
}
}
},Cesium.ScreenSpaceEventType.MOUSE_MOVE);
//双击完成绘制飞行路线操作
handler.setInputAction(function(movement)
{
handler.destroy();
if(positions.length>0)
{
positions[0].height = 0;
positions[positions.length-1].height =0;
//先停止之前的飞行,初始化飞行数据,开始飞行
stopFly(false);
if(lnglatPositions.length>2)
{
lnglatPositions.splice(lnglatPositions.length-1,1);
mFlyPath[0] = lnglatPositions;
initFly();
startFly();
}
}
},Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
}
/**
* 停止飞行
**/
function stopFly(clearData)
{
viewer.trackedEntity = undefined;
var start = Cesium.JulianDate.fromDate(new Date());
viewer.clock.startTime = start.clone();
var stop = Cesium.JulianDate.addSeconds(start, 300000000, new Cesium.JulianDate());
viewer.clock.stopTime = stop.clone();
viewer.entities.removeAll();
if(clearData)
mFlyPath = [];
}
/**
* 键盘控制飞行
**/
function flyByKeyword()
{
viewer.entities.removeAll();
viewer.scene.primitives.removeAll();
let display = document.getElementsByClassName("flyByKeywordContainer")[0].style.display;
if(display == 'block')
document.getElementsByClassName("flyByKeywordContainer")[0].style.display="none";
else
document.getElementsByClassName("flyByKeywordContainer")[0].style.display="block";
var canvas = viewer.canvas;
canvas.setAttribute('tabindex', '0'); // needed to put focus on the canvas
canvas.addEventListener('click', function() {
canvas.focus();
});
canvas.focus();
var scene = viewer.scene;
var pathPosition = new Cesium.SampledPositionProperty();
var entityPath = viewer.entities.add({
position : pathPosition,
name : 'path',
path : {
show : true,
leadTime : 0,
trailTime : 60,
width : 10,
resolution : 1,
material : new Cesium.PolylineGlowMaterialProperty({
glowPower : 0.3,
taperPower : 0.3,
color : Cesium.Color.PALEGOLDENROD
})
}
});
var camera = viewer.camera;
var controller = scene.screenSpaceCameraController;
var r = 0;
var center = new Cesium.Cartesian3();
var hpRoll = new Cesium.HeadingPitchRoll();
var hpRange = new Cesium.HeadingPitchRange();
var speed = 10;
var deltaRadians = Cesium.Math.toRadians(3.0);
var position = Cesium.Cartesian3.fromDegrees(116.0744619, 39.0503706, 5000.0);
var speedVector = new Cesium.Cartesian3();
var fixedFrameTransform = Cesium.Transforms.localFrameToFixedFrameGenerator('north', 'west');
var planePrimitive = scene.primitives.add(Cesium.Model.fromGltf({
url : '../../3dmap/Apps/SampleData/models/CesiumAir/Cesium_Air.glb',
modelMatrix : Cesium.Transforms.headingPitchRollToFixedFrame(position, hpRoll, Cesium.Ellipsoid.WGS84, fixedFrameTransform),
minimumPixelSize : 128
}));
planePrimitive.readyPromise.then(function(model) {
// Play and loop all animations at half-speed
model.activeAnimations.addAll({
multiplier : 0.5,
loop : Cesium.ModelAnimationLoop.REPEAT
});
// Zoom to model
r = 2.0 * Math.max(model.boundingSphere.radius, camera.frustum.near);
controller.minimumZoomDistance = r * 0.5;
Cesium.Matrix4.multiplyByPoint(model.modelMatrix, model.boundingSphere.center, center);
var heading = Cesium.Math.toRadians(230.0);
var pitch = Cesium.Math.toRadians(-20.0);
hpRange.heading = heading;
hpRange.pitch = pitch;
hpRange.range = r * 50.0;
camera.lookAt(center, hpRange);
});
document.addEventListener('keydown', function(e) {
switch (e.keyCode) {
case 40:
if (e.shiftKey) {
// speed down
speed = Math.max(--speed, 1);
} else {
// pitch down
hpRoll.pitch -= deltaRadians;
if (hpRoll.pitch < -Cesium.Math.TWO_PI) {
hpRoll.pitch += Cesium.Math.TWO_PI;
}
}
break;
case 38:
if (e.shiftKey) {
// speed up
speed = Math.min(++speed, 100);
} else {
// pitch up
hpRoll.pitch += deltaRadians;
if (hpRoll.pitch > Cesium.Math.TWO_PI) {
hpRoll.pitch -= Cesium.Math.TWO_PI;
}
}
break;
case 39:
if (e.shiftKey) {
// roll right
hpRoll.roll += deltaRadians;
if (hpRoll.roll > Cesium.Math.TWO_PI) {
hpRoll.roll -= Cesium.Math.TWO_PI;
}
} else {
// turn right
hpRoll.heading += deltaRadians;
if (hpRoll.heading > Cesium.Math.TWO_PI) {
hpRoll.heading -= Cesium.Math.TWO_PI;
}
}
break;
case 37:
if (e.shiftKey) {
// roll left until
hpRoll.roll -= deltaRadians;
if (hpRoll.roll < 0.0) {
hpRoll.roll += Cesium.Math.TWO_PI;
}
} else {
// turn left
hpRoll.heading -= deltaRadians;
if (hpRoll.heading < 0.0) {
hpRoll.heading += Cesium.Math.TWO_PI;
}
}
break;
default:
}
});
var headingSpan = document.getElementById('heading');
var pitchSpan = document.getElementById('pitch');
var rollSpan = document.getElementById('roll');
var speedSpan = document.getElementById('speed');
var fromBehind = document.getElementById('fromBehind');
viewer.scene.preUpdate.addEventListener(function(scene, time) {
speedVector = Cesium.Cartesian3.multiplyByScalar(Cesium.Cartesian3.UNIT_X, speed / 10, speedVector);
position = Cesium.Matrix4.multiplyByPoint(planePrimitive.modelMatrix, speedVector, position);
pathPosition.addSample(Cesium.JulianDate.now(), position);
Cesium.Transforms.headingPitchRollToFixedFrame(position, hpRoll, Cesium.Ellipsoid.WGS84, fixedFrameTransform, planePrimitive.modelMatrix);
if (fromBehind.checked) {
// Zoom to model
Cesium.Matrix4.multiplyByPoint(planePrimitive.modelMatrix, planePrimitive.boundingSphere.center, center);
hpRange.heading = hpRoll.heading;
hpRange.pitch = hpRoll.pitch;
camera.lookAt(center, hpRange);
}
});
viewer.scene.preRender.addEventListener(function(scene, time) {
headingSpan.innerHTML = Cesium.Math.toDegrees(hpRoll.heading).toFixed(1);
pitchSpan.innerHTML = Cesium.Math.toDegrees(hpRoll.pitch).toFixed(1);
rollSpan.innerHTML = Cesium.Math.toDegrees(hpRoll.roll).toFixed(1);
speedSpan.innerHTML = speed.toFixed(1);
});
}
</script>
</body>
</html>