513 lines
20 KiB
HTML
513 lines
20 KiB
HTML
<!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/3d/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: '../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 : '../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> |