cesium-examples/map/examples/fly.html

513 lines
20 KiB
HTML
Raw Permalink Normal View History

<!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>
2019-11-21 15:46:14 +08:00
<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: {
2019-11-21 15:46:14 +08:00
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({
2019-11-21 15:46:14 +08:00
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>