|
|
|
@ -0,0 +1,348 @@
|
|
|
|
|
<!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>飞行轨迹回放</title>
|
|
|
|
|
<script type="text/javascript" cesium="true" src="https://api.tianditu.gov.cn/cdn/demo/sanwei/static/cesium/Cesium.js"></script>
|
|
|
|
|
<script type="text/javascript" cesium="true" src="https://api.tianditu.gov.cn/cdn/plugins/cesium/Cesium_ext_min.js"></script>
|
|
|
|
|
<link rel="stylesheet" cesium="true" href="https://api.tianditu.gov.cn/cdn/demo/sanwei/static/cesium/Widgets/widgets.css">
|
|
|
|
|
<link href="https://services.arcgisonline.com/arcgis/rest/static/jsapi-template-main.css" rel="stylesheet" type="text/css">
|
|
|
|
|
<link href="https://js.arcgis.com/4.14/esri/css/main.css" rel="stylesheet" type="text/css">
|
|
|
|
|
<script type="text/javascript" src="https://js.arcgis.com/4.14/dojo/dojo.js"></script>
|
|
|
|
|
<script type="text/javascript" src="/Public/js/datasource.js"></script>
|
|
|
|
|
<script src="/Public/js/jquery-1.10.2.min.js"></script>
|
|
|
|
|
<style>
|
|
|
|
|
html,
|
|
|
|
|
body,
|
|
|
|
|
#cesiumContainer {
|
|
|
|
|
width: 100%;
|
|
|
|
|
height: 100%;
|
|
|
|
|
margin: 0;
|
|
|
|
|
padding: 0;
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
}
|
|
|
|
|
</style>
|
|
|
|
|
</head>
|
|
|
|
|
<body>
|
|
|
|
|
<div id="cesiumContainer"></div>
|
|
|
|
|
<script>
|
|
|
|
|
// var viewer = new Cesium.Viewer("cesiumContainer");
|
|
|
|
|
// viewer.baseLayerPicker.viewModel.selectedImagery = viewer.baseLayerPicker.viewModel.imageryProviderViewModels[12];
|
|
|
|
|
|
|
|
|
|
var token = "72e2e7be836401af7e79c232285a552e";
|
|
|
|
|
var tdtUrl = 'http://t{s}.tianditu.gov.cn/';
|
|
|
|
|
var subdomains = ['0', '1', '2', '3', '4', '5', '6', '7'];
|
|
|
|
|
|
|
|
|
|
Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI3NzI3MDQwMS05M2MxLTQ1MDAtOWYxOS0wZDg0MmI5Zjc2NTUiLCJpZCI6MjMxNzM1LCJpYXQiOjE3MjIzODk2ODB9.zy6rmwWtDzF2890HZR6XGlDxxMImZ8v_Erfnz3gyti4';
|
|
|
|
|
// cesium 初始化
|
|
|
|
|
var viewer = new Cesium.Viewer('cesiumContainer', {
|
|
|
|
|
shouldAnimate: true, //是否允许动画
|
|
|
|
|
selectionIndicator: false,
|
|
|
|
|
baseLayerPicker: true,
|
|
|
|
|
fullscreenButton: false,
|
|
|
|
|
geocoder: false,
|
|
|
|
|
homeButton: false,
|
|
|
|
|
infoBox: false,
|
|
|
|
|
sceneModePicker: false,
|
|
|
|
|
timeline: true,
|
|
|
|
|
navigationHelpButton: false,
|
|
|
|
|
navigationInstructionsInitiallyVisible: false,
|
|
|
|
|
showRenderLoopErrors: false,
|
|
|
|
|
shadows: false,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
viewer.baseLayerPicker.viewModel.selectedImagery = viewer.baseLayerPicker.viewModel.imageryProviderViewModels[12];
|
|
|
|
|
viewer.baseLayerPicker.container.style.display = "none";
|
|
|
|
|
|
|
|
|
|
let positionDisplay = addComponent('div', 'absolute', '10px', '10px', '5px', 'white', 1000);
|
|
|
|
|
let buttonNorth = addComponent('button', 'absolute', '50px', '10px', '5px', 'white', 1000, '朝北视角');
|
|
|
|
|
let buttonEast = addComponent('button', 'absolute', '50px', '80px', '5px', 'white', 1000, '朝东视角');
|
|
|
|
|
let buttonSouth = addComponent('button', 'absolute', '50px', '150px', '5px', 'white', 1000, '朝南视角');
|
|
|
|
|
let buttonWest = addComponent('button', 'absolute', '50px', '220px', '5px', 'white', 1000, '朝西视角');
|
|
|
|
|
let buttonCenter = addComponent('button', 'absolute', '50px', '290px', '5px', 'white', 1000, '座舱视角');
|
|
|
|
|
|
|
|
|
|
buttonNorth.addEventListener('click', function () {
|
|
|
|
|
switchCameraView(0);
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
buttonEast.addEventListener('click', function () {
|
|
|
|
|
switchCameraView(90);
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
buttonSouth.addEventListener('click', function () {
|
|
|
|
|
switchCameraView(180);
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
buttonWest.addEventListener('click', function () {
|
|
|
|
|
switchCameraView(270);
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let postUpdateEventListener = null;
|
|
|
|
|
buttonCenter.addEventListener('click', function () {
|
|
|
|
|
viewer.trackedEntity.model.uri = plan;
|
|
|
|
|
viewer.trackedEntity.model.scale=2;
|
|
|
|
|
let prePoint = null;
|
|
|
|
|
|
|
|
|
|
viewer.scene.postUpdate.addEventListener(
|
|
|
|
|
postUpdateEventListener = () => {
|
|
|
|
|
|
|
|
|
|
let curPoint = viewer.trackedEntity.position.getValue(viewer.clock.currentTime);
|
|
|
|
|
|
|
|
|
|
if (prePoint) {
|
|
|
|
|
// 计算heading-代表 Z 轴旋转
|
|
|
|
|
let heading = getHeading(prePoint, curPoint);
|
|
|
|
|
//let heading = - Cesium.Math.PI_OVER_TWO;
|
|
|
|
|
// 计算pitch-代表 Y 轴朝向
|
|
|
|
|
//let pitch = Cesium.Math.toRadians(-150);
|
|
|
|
|
let pitch = Cesium.Math.toRadians(-15);
|
|
|
|
|
let range = 20
|
|
|
|
|
|
|
|
|
|
viewer.scene.camera.lookAt(curPoint, new Cesium.HeadingPitchRange(heading, pitch, range));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 当前点在下一次渲染时为前一个点
|
|
|
|
|
prePoint = Cesium.Cartesian3.clone(curPoint)
|
|
|
|
|
|
|
|
|
|
});
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//viewer.animation.container.style.display = "none";
|
|
|
|
|
// 抗锯齿
|
|
|
|
|
viewer.scene.fxaa = true;
|
|
|
|
|
viewer.scene.postProcessStages.fxaa.enabled = false;
|
|
|
|
|
// 水雾特效
|
|
|
|
|
viewer.scene.globe.showGroundAtmosphere = true;
|
|
|
|
|
// 设置最大俯仰角,[-90,0]区间内,默认为-30,单位弧度
|
|
|
|
|
// viewer.scene.screenSpaceCameraController.constrainedPitch = Cesium.Math.toRadians(-20);
|
|
|
|
|
// viewer.scene.screenSpaceCameraController.autoResetHeadingPitch = false;
|
|
|
|
|
// viewer.scene.screenSpaceCameraController.inertiaZoom = 0.5;
|
|
|
|
|
// viewer.scene.screenSpaceCameraController.minimumZoomDistance = 50;
|
|
|
|
|
// viewer.scene.screenSpaceCameraController.maximumZoomDistance = 20000000;
|
|
|
|
|
// viewer.scene.screenSpaceCameraController.zoomEventTypes = [
|
|
|
|
|
// Cesium.CameraEventType.RIGHT_DRAG,
|
|
|
|
|
// Cesium.CameraEventType.WHEEL,
|
|
|
|
|
// Cesium.CameraEventType.PINCH,
|
|
|
|
|
// ];
|
|
|
|
|
// viewer.scene.screenSpaceCameraController.tiltEventTypes = [
|
|
|
|
|
// Cesium.CameraEventType.MIDDLE_DRAG,
|
|
|
|
|
// Cesium.CameraEventType.PINCH,
|
|
|
|
|
// {
|
|
|
|
|
// eventType: Cesium.CameraEventType.LEFT_DRAG,
|
|
|
|
|
// modifier: Cesium.KeyboardEventModifier.CTRL,
|
|
|
|
|
// },
|
|
|
|
|
// {
|
|
|
|
|
// eventType: Cesium.CameraEventType.RIGHT_DRAG,
|
|
|
|
|
// modifier: Cesium.KeyboardEventModifier.CTRL,
|
|
|
|
|
// },
|
|
|
|
|
// ];
|
|
|
|
|
// 取消默认的双击事件
|
|
|
|
|
viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
|
|
|
|
|
|
|
|
|
|
var esriImg = new Cesium.ArcGisMapServerImageryProvider({
|
|
|
|
|
url: 'https://services.arcgisonline.com/arcgis/rest/services/World_Imagery/MapServer',
|
|
|
|
|
});
|
|
|
|
|
viewer.imageryLayers.addImageryProvider(esriImg);
|
|
|
|
|
// 叠加影像服务
|
|
|
|
|
// var imgMap = new Cesium.UrlTemplateImageryProvider({
|
|
|
|
|
// url: tdtUrl + 'img_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=img&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=' + token,
|
|
|
|
|
// subdomains: subdomains,
|
|
|
|
|
// tilingScheme : new Cesium.WebMercatorTilingScheme(),
|
|
|
|
|
// maximumLevel : 18
|
|
|
|
|
// });
|
|
|
|
|
// viewer.imageryLayers.addImageryProvider(imgMap);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//将三维球定位到中国
|
|
|
|
|
// viewer.camera.flyTo({
|
|
|
|
|
// destination: Cesium.Cartesian3.fromDegrees(116.40375810947471, 39.908597112062225, 17850000),
|
|
|
|
|
// orientation: {
|
|
|
|
|
// heading: Cesium.Math.toRadians(348.4202942851978),
|
|
|
|
|
// pitch: Cesium.Math.toRadians(-89.74026687972041),
|
|
|
|
|
// roll: Cesium.Math.toRadians(0)
|
|
|
|
|
// },
|
|
|
|
|
// complete: function callback() {
|
|
|
|
|
// // 定位完成之后的回调函数
|
|
|
|
|
// }
|
|
|
|
|
// });
|
|
|
|
|
|
|
|
|
|
let date = new Date('2024-08-06 13:22:04');
|
|
|
|
|
const start = Cesium.JulianDate.fromDate(date);
|
|
|
|
|
const end = 7000;
|
|
|
|
|
var plan = "../Public/Cesium_Air.glb"
|
|
|
|
|
|
|
|
|
|
const czml = [
|
|
|
|
|
{
|
|
|
|
|
id: "document",
|
|
|
|
|
version: "1.0",
|
|
|
|
|
clock: {
|
|
|
|
|
interval: `${Cesium.JulianDate.toIso8601(start, 0)}/${Cesium.JulianDate.toIso8601(Cesium.JulianDate.addSeconds(start, end, new Cesium.JulianDate()), 0)}`,
|
|
|
|
|
currentTime: `${Cesium.JulianDate.toIso8601(start, 0)}`,
|
|
|
|
|
multiplier: 6,
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
id: "plane",
|
|
|
|
|
availability: `${Cesium.JulianDate.toIso8601(start, 0)}/${Cesium.JulianDate.toIso8601(Cesium.JulianDate.addSeconds(start, end, new Cesium.JulianDate()), 0)}`,
|
|
|
|
|
model: {
|
|
|
|
|
gltf: plan,
|
|
|
|
|
scale: 2.0,
|
|
|
|
|
minimumPixelSize: 48,
|
|
|
|
|
maximumScale: 2000,
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// viewFrom: {
|
|
|
|
|
// cartesian: [-2080, -1715, 779]
|
|
|
|
|
// },
|
|
|
|
|
orientation: {velocityReference: "#position"},
|
|
|
|
|
path: {
|
|
|
|
|
material: {
|
|
|
|
|
solidColor: {
|
|
|
|
|
color: {
|
|
|
|
|
interval: `${Cesium.JulianDate.toIso8601(start, 0)}/${Cesium.JulianDate.toIso8601(Cesium.JulianDate.addSeconds(start, end, new Cesium.JulianDate()), 0)}`,
|
|
|
|
|
rgba: [0, 205, 255, 255]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
width: [
|
|
|
|
|
{
|
|
|
|
|
interval: `${Cesium.JulianDate.toIso8601(start, 0)}/${Cesium.JulianDate.toIso8601(Cesium.JulianDate.addSeconds(start, end, new Cesium.JulianDate()), 0)}`,
|
|
|
|
|
number: 3
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
show: [
|
|
|
|
|
{
|
|
|
|
|
interval: `${Cesium.JulianDate.toIso8601(start, 0)}/${Cesium.JulianDate.toIso8601(Cesium.JulianDate.addSeconds(start, end, new Cesium.JulianDate()), 0)}`,
|
|
|
|
|
boolean: true
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
position: {
|
|
|
|
|
interpolationAlgorithm: "LAGRANGE",
|
|
|
|
|
interpolationDegree: 5,
|
|
|
|
|
epoch: `${Cesium.JulianDate.toIso8601(start, 0)}`,
|
|
|
|
|
cartographicDegrees:ds
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
];
|
|
|
|
|
let dataSource = viewer.dataSources.add(Cesium.CzmlDataSource.load(czml));
|
|
|
|
|
viewer.zoomTo(dataSource);
|
|
|
|
|
|
|
|
|
|
dataSource.then(part => {
|
|
|
|
|
// 根据id获取czml中的模型
|
|
|
|
|
let e = part.entities.getById("plane");
|
|
|
|
|
// 相机跟随模型
|
|
|
|
|
viewer.trackedEntity = e;
|
|
|
|
|
//++++++++++++++// 视角跟随模型
|
|
|
|
|
let prePoint = null;
|
|
|
|
|
// 前一个点
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
viewer.scene.postRender.addEventListener(() => {
|
|
|
|
|
if (e && viewer.clock.shouldAnimate) {
|
|
|
|
|
// 获取当前时间的位置
|
|
|
|
|
let curPoint = e.position.getValue(viewer.clock.currentTime);
|
|
|
|
|
if (prePoint) {
|
|
|
|
|
// 计算heading-代表 Z 轴旋转
|
|
|
|
|
let heading = getHeading(prePoint, curPoint);
|
|
|
|
|
//let heading = - Cesium.Math.PI_OVER_TWO;
|
|
|
|
|
// 计算pitch-代表 Y 轴朝向
|
|
|
|
|
//let pitch = Cesium.Math.toRadians(-150);
|
|
|
|
|
let pitch = Cesium.Math.toRadians(-10);
|
|
|
|
|
let range = 10;
|
|
|
|
|
|
|
|
|
|
//viewer.camera.lookAt(curPoint, new Cesium.HeadingPitchRange(heading, pitch, range));
|
|
|
|
|
|
|
|
|
|
let cartographicPosition = Cesium.Cartographic.fromCartesian(curPoint);
|
|
|
|
|
let longitude = Cesium.Math.toDegrees(cartographicPosition.longitude);
|
|
|
|
|
let latitude = Cesium.Math.toDegrees(cartographicPosition.latitude);
|
|
|
|
|
let headingDegrees = Cesium.Math.toDegrees(heading);
|
|
|
|
|
let height = cartographicPosition.height;
|
|
|
|
|
positionDisplay.textContent =
|
|
|
|
|
//"Longitude: " + longitude + "\u00B0" + "\n" +
|
|
|
|
|
//"Latitude: " + latitude + "\u00B0" + "\n" +
|
|
|
|
|
"Height: " + height.toFixed(2) + "M" + "\n" +
|
|
|
|
|
"航向:" + headingDegrees.toFixed(2) + "\u00B0";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 当前点在下一次渲染时为前一个点
|
|
|
|
|
prePoint = Cesium.Cartesian3.clone(curPoint)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
function getHeading(pointA, pointB) {
|
|
|
|
|
//建立以点A为原点,X轴为east,Y轴为north,Z轴朝上的坐标系
|
|
|
|
|
const transform = Cesium.Transforms.eastNorthUpToFixedFrame(pointA);
|
|
|
|
|
//向量AB
|
|
|
|
|
const positionvector = Cesium.Cartesian3.subtract(pointB, pointA, new Cesium.Cartesian3());
|
|
|
|
|
//因transform是将A为原点的eastNorthUp坐标系中的点转换到世界坐标系的矩阵
|
|
|
|
|
//AB为世界坐标中的向量
|
|
|
|
|
//因此将AB向量转换为A原点坐标系中的向量,需乘以transform的逆矩阵。
|
|
|
|
|
const vector = Cesium.Matrix4.multiplyByPointAsVector(Cesium.Matrix4.inverse(transform, new Cesium.Matrix4()), positionvector, new Cesium.Cartesian3());
|
|
|
|
|
//归一化
|
|
|
|
|
const direction = Cesium.Cartesian3.normalize(vector, new Cesium.Cartesian3());
|
|
|
|
|
//heading
|
|
|
|
|
|
|
|
|
|
const heading = Math.atan2(direction.y, direction.x) - Cesium.Math.PI_OVER_TWO;
|
|
|
|
|
//console.log(direction.y, direction.x,Math.atan2(direction.y, direction.x),heading,Cesium.Math.TWO_PI - Cesium.Math.zeroToTwoPi(heading));
|
|
|
|
|
//return Cesium.Math.TWO_PI - Cesium.Math.zeroToTwoPi(heading) - Cesium.Math.PI_OVER_TWO;
|
|
|
|
|
return Cesium.Math.TWO_PI - Cesium.Math.zeroToTwoPi(heading);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function updatePosition() {
|
|
|
|
|
var camera = viewer.scene.camera;
|
|
|
|
|
var ellipsoid = viewer.scene.globe.ellipsoid;
|
|
|
|
|
var cartesian = camera.position;
|
|
|
|
|
var height = ellipsoid.cartesianToCartographic(cartesian).height;
|
|
|
|
|
var text = "Latitude: " + camera.positionCartographic.latitude.toDegrees() + "\u00B0" + "\n" +
|
|
|
|
|
"Longitude: " + camera.positionCartographic.longitude.toDegrees() + "\u00B0" + "\n" +
|
|
|
|
|
"Height: " + height + "m";
|
|
|
|
|
positionDisplay.textContent = text;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function addComponent(name, position, top, left, padding, backgroundColor, zindex, text = '') {
|
|
|
|
|
let component = document.createElement(name);
|
|
|
|
|
component.style.position = position;
|
|
|
|
|
if (text !== undefined || text !== '') {
|
|
|
|
|
component.innerHTML = text;
|
|
|
|
|
}
|
|
|
|
|
component.style.top = top;
|
|
|
|
|
component.style.left = left;
|
|
|
|
|
component.style.zIndex = zindex;
|
|
|
|
|
component.style.backgroundColor = backgroundColor;
|
|
|
|
|
component.style.padding = padding;
|
|
|
|
|
document.body.appendChild(component);
|
|
|
|
|
return component;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function switchCameraView(heading)
|
|
|
|
|
{
|
|
|
|
|
viewer.scene.postUpdate.removeEventListener(postUpdateEventListener);
|
|
|
|
|
viewer.trackedEntity.model.uri = plan;
|
|
|
|
|
viewer.trackedEntity.model.scale=3;
|
|
|
|
|
heading = Cesium.Math.toRadians(heading);
|
|
|
|
|
// 计算pitch-代表 Y 轴朝向
|
|
|
|
|
//let pitch = Cesium.Math.toRadians(-150);
|
|
|
|
|
let pitch = Cesium.Math.toRadians(-10);
|
|
|
|
|
let range = 200;
|
|
|
|
|
|
|
|
|
|
let point = viewer.scene.camera.position
|
|
|
|
|
viewer.scene.camera.lookAt(point, new Cesium.HeadingPitchRange(heading, pitch, range));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
</script>
|
|
|
|
|
</body>
|
|
|
|
|
</html>
|