learning_cesium/Camera相机系统.html

341 lines
13 KiB
HTML
Raw Permalink Normal View History

2024-03-19 18:06:25 +08:00
<!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>
<!-- 引入样式 -->
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
<!-- 引入组件库 -->
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
<style>
@import url(./Build/Cesium/Widgets/widgets.css);
html,
body,
#cesiumContainer {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
overflow: hidden;
}
#credit {
display: none;
}
#btnContainer {
position: absolute;
top: 50px;
left: 150px;
z-index: 99999999;
}
</style>
</head>
<body>
<div id="cesiumContainer"></div>
<div id="credit"></div>
<div id="btnContainer">
<el-row>
<el-button @click="setView">setView</el-button>
<el-button @click="flyTo">flyTo</el-button>
<el-button @click="flyToPosition">flyToPosition</el-button>
<el-button @click="flyToRectangle">flyToRectangle</el-button>
<el-button @click="flyToEasing">flyToEasing</el-button>
<el-button @click="lookAt">lookAt</el-button>
<el-button @click="lookAtTransform">lookAtTransform</el-button>
</el-row>
</div>
<script>
/**
三维的GIS中移动视域范围不仅要确定视点的位置还要确定视线的方向
Cesium通过相机控制场景中的视域旋转、缩放、平移
主要用两个参数设置相机的状态:
1.position位置使用一个三维的笛卡尔空间坐标点x,y,z
2.orientation方向(heading水平方向、pitch俯仰角、roll翻滚角)欧拉角
操作相机的常用方法有:
1.setView:通过定义相机的位置和实现方向来控制,没有过渡动画,适合快速切换视角。
2.viewBoundingSphere:也没有过渡动画,区别在于该方法必须设定模型的外接圆,适合室内浏览,因为室内空间较小,相机移动的幅度不易控制
视点位于外接球的球心,可以设置偏移。
3.flyTo:具有空中飞行的过渡动画效果可以设置飞行时间。如果场景secne中添加了矢量数据模型或几何对象可以使用该方法进行聚焦如Entity, EntityCollection, DataSource, Cesium3DTilset, and much more.
4.lookAt:将视角固定在所设置的目的点上,用户可以通过鼠标任意旋转视角方向,但不会改变其位置,同时缩放会失效,中轮滚动事件也会失效。
5.lookAtTransform:将相机锁定在某个点上
*/
Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI5ZjRjNTZkNC01NDYxLTRhMjQtOGEwZC1kZjA3YzQ5YTJlZDkiLCJpZCI6MjYwODQsInNjb3BlcyI6WyJhc3IiLCJnYyJdLCJpYXQiOjE1ODcxOTMwODN9.prGsSKyAW_9Ow5zHYPhbm3LsQL-ApQw5-5PNJkDaHi8';
new Vue({
el: '#btnContainer',
data: function () {
return {
viewer: null,
directions:{
forward:false,
backward:false,
up:false,
down:false,
left:false,
right:false,
twistLeft:false,
twistRight:false
}
}
},
mounted:function(){
this.initCesium();
this.initEvent();
},
methods:{
initCesium:function(){
/**
* Viewer对象
* 用于构建应用程序的基本小部件。它将所有标准的Cesium部件组合到一个可重用的包中。
* 小部件可以通过使用mixin来扩展来添加对各种应用程序有用的功能
*/
//Initialize the viewer widget with several custom options and mixins.
this.viewer = new Cesium.Viewer('cesiumContainer', {
/**
* 场景模式,默认SceneMode.SCENE3D
* SceneMode:指定场景是3D/2D/2.5D,可选值:
* MORPHING在模式之间变形如3D转2D
* COLUMBUS_VIEW2.5D视角,地图会被平铺,高度为非零的对象被绘制在上面。
* SCENE2D:2D模式地图会被自顶向下正射投影
* SCENE3D3D模式一个传统的三维视角的全球。
*/
// sceneMode : Cesium.SceneMode.COLUMBUS_VIEW,
sceneMode: Cesium.SceneMode.SCENE3D,
//指定椭球面提供地形或其他几何图形数据,
terrainProvider: Cesium.createWorldTerrain(),
//指定影像数据的数据源,该选项只有在baseLayerPicker设置为false时生效
imageryProvider : new Cesium.OpenStreetMapImageryProvider({
url : 'https://a.tile.openstreetmap.org/'
}),
// imageryProvider: new Cesium.WebMapTileServiceImageryProvider({
// url: 'http://t0.tianditu.gov.cn/img_w/wmts?tk=ebf64362215c081f8317203220f133eb',
// layer: 'img',
// style: 'default',
// tileMatrixSetID: 'w',
// format: 'tiles',
// maximumLevel: 18
// }),
//设置背景,如果为false则星星/月亮/太阳都不会渲染
// skyBox : new Cesium.SkyBox({
// sources : {
// positiveX : 'stars/100_BK.jpg',
// negativeX : 'stars/100_BK.jpg',
// positiveY : 'stars/100_BK.jpg',
// negativeY : 'stars/100_BK.jpg',
// positiveZ : 'stars/100_BK.jpg',
// negativeZ : 'stars/100_BK.jpg'
// }
// }),
// Show Columbus View map with Web Mercator projection
mapProjection: new Cesium.WebMercatorProjection(),
geocoder: false,//位置查找
homeButton: false,//视图返回初始位置
sceneModePicker: false,//视角选择器
baseLayerPicker: false,//底图选择器
navigationHelpButton: false,//导航帮助按钮
animation: false,//动画控制器
creditContainer: "credit",//版权显示,指定dom对象的id,再通过id样式可以隐藏CESIUM 版本图标
timeline: false,//时间线
fullscreenButton: false,//全屏控件
vrButton: false,
infoBox:false,
shouldAnimate:true,
scene3DOnly: true,//默认false若为true,所有几何体实例将仅会在3D模式中渲染(在GPU内存中)
});
//Add basic drag and drop functionality
this.viewer.extend(Cesium.viewerDragDropMixin);
//Show a pop-up alert if we encounter an error when processing a dropped file
this.viewer.dropError.addEventListener(function (dropHandler, name, error) {
console.log(error);
window.alert(error);
});
},
setView:function(){
var position = Cesium.Cartesian3.fromDegrees(113.331875,23.110038,10000000);
this.viewer.camera.setView({
destination: position,
orientation: {
heading: Cesium.Math.toRadians(0.0),//使用弧度的形式
pitch: Cesium.Math.toRadians(-70.0),
roll: 0.0
}
})
},
flyTo:function(){
var position = Cesium.Cartesian3.fromDegrees(-113.331875,19.110038,10000000);
this.viewer.camera.flyTo({
destination: position,
orientation: {//使用欧拉角
heading: Cesium.Math.toRadians(0.0),//使用弧度的形式
pitch: Cesium.Math.toRadians(-60.0),
roll: 0.0
},
duration:3,//设置飞行时间,单位为秒
complete:function(){
console.log("动画完成后的回调!")
},
cancel:function(){
console.log("动画被取消后的回调!")
},
maximumHeight:5000,//最大的飞行高度
})
},
flyToPosition :function(){
this.viewer.camera.flyTo({
destination : Cesium.Cartesian3.fromDegrees(-117.16, 32.71, 15000.0)
});
},
flyToRectangle:function(){
var west = -90.0;
var south = 38.0;
var east = -87.0;
var north = 40.0;
var rectangle = this.viewer.entities.add({
rectangle: {
coordinates: Cesium.Rectangle.fromDegrees(west, south, east, north),
},
});
this.viewer.flyTo(rectangle);
// this.viewer.camera.flyTo({
// destination :Cesium.Rectangle.fromDegrees(west, south, east, north)
// });
},
flyToEasing:function(){
var that = this;
that.viewer.camera.flyTo({
destination : new Cesium.Cartesian3(-3961951.575572026, 3346492.0945766014, 3702340.5336036095),
orientation : {
direction : new Cesium.Cartesian3(0.8982074415844437, -0.4393530288745287, 0.013867512433959908),
up : new Cesium.Cartesian3(0.12793638617798253, 0.29147314437764565, 0.9479850669701113),
},
complete: function () {
// setTimeout(function () {
// that.viewer.camera.flyTo({
// destination : new Cesium.Cartesian3(-2304817.2435183465, -3639113.128132953, 4688495.013644141),
// orientation : {
// direction : new Cesium.Cartesian3(0.3760550186878076, 0.9007147395506565, 0.21747547189489164),
// up : new Cesium.Cartesian3(-0.20364591529594356, -0.14862471084230877, 0.9676978022659334),
// },
// easingFunction: Cesium.EasingFunction.QUADRATIC_IN_OUT,
// duration: 5
// });
// }, 1000);
},
});
},
lookAt:function(){
var center = Cesium.Cartesian3.fromDegrees(113.331875,19.110038,5000000);
var heading = Cesium.Math.toRadians(0);
var pitch = Cesium.Math.toRadians(-90.0);
var range = 50;
this.viewer.camera.lookAt(center,new Cesium.HeadingPitchRange(heading,pitch,range));
},
lookAtTransform:function(){
// 1. Using a cartesian offset
// var center = Cesium.Cartesian3.fromRadians(2.4213211833389243, 0.6171926869414084, 3626.0426275055174);
// var transform = Cesium.Transforms.eastNorthUpToFixedFrame(center);
// this.viewer.camera.lookAtTransform(transform, new Cesium.Cartesian3(0.0, -4790000.0, 3930000.0));
// 2. Using a HeadingPitchRange offset
var center = Cesium.Cartesian3.fromRadians(2.4213211833389243, 0.6171926869414084, 3626.0426275055174);
var transform = Cesium.Transforms.eastNorthUpToFixedFrame(center);
this.viewer.scene.camera.lookAtTransform(transform, new Cesium.HeadingPitchRange(0, -Math.PI/4, 2900));
},
initEvent:function(){
var that = this;
/**
* 绑定键盘事件,实现使用键盘操作相机的视域移动
*/
document.addEventListener("keydown",function(e){
var direction = that.getDirectionForKeyCode(e.keyCode);
if(typeof direction !== 'undefined'){
that.directions[direction] = true;
}
})
document.addEventListener("keyup",function(e){
var direction = that.getDirectionForKeyCode(e.keyCode);
if(typeof direction !== 'undefined'){
that.directions[direction] = false;
}
})
this.viewer.clock.onTick.addEventListener(function(clock){
var camera = that.viewer.camera;
var ellipsoid = that.viewer.scene.globe.ellipsoid;
var cameraHeight = ellipsoid.cartesianToCartographic(camera.position).height;
var moveRate = cameraHeight/100.0;
that.directions.forward&&camera.moveForward(moveRate);
that.directions.backward&&camera.moveBackward(moveRate);
that.directions.up&&camera.moveUp(moveRate);
that.directions.down&&camera.moveDown(moveRate);
that.directions.left&&camera.moveLeft(moveRate);
that.directions.right&&camera.moveRight(moveRate);
that.directions.twistLeft&&camera.twistLeft(moveRate);
that.directions.twistRight&&camera.twistRight(moveRate);
})
},
getDirectionForKeyCode:function(keyCode){
switch(keyCode){
case "W".charCodeAt(0):
return "forward";
case "S".charCodeAt(0):
return "backward";
case "A".charCodeAt(0):
return "left";
case "D".charCodeAt(0):
return "right";
case "Q".charCodeAt(0):
return "up";
case "E".charCodeAt(0):
return "down";
case "F".charCodeAt(0):
return "twistLeft";
case "G".charCodeAt(0):
return "twistRight";
}
}
}
})
//Secne场景中执行调用图层、3D Tiles数据加载、场景交互等功能以及一些场景数据加载Primitivew API
//Secne中的camera属性与Scene中的camera属性相同。
// var scene = viewer.scene;
// //加载3D tiles格式的三维模型
// var tileset = new Cesium.Cesium3DTileset({
// url:"./SampleData/Cesium3DTiles/Tilesets/Tileset/tileset.json"
// });
// tileset.readyPromise.then(function(tileset){
// viewer.scene.primitives.add(tileset);
// viewer.camera.viewBoundingSphere(tileset.boundingSphere,new Cesium.HeadingPitchRange(-1.57,0,2))
// })
</script>
</body>
</html>